LCOV - code coverage report
Current view: top level - gcc - ifcvt.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 74.5 % 2732 2035
Test Date: 2026-02-28 14:20:25 Functions: 85.9 % 78 67
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* If-conversion support.
       2              :    Copyright (C) 2000-2026 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 3, 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 COPYING3.  If not see
      18              :    <http://www.gnu.org/licenses/>.  */
      19              : 
      20              : #include "config.h"
      21              : #include "system.h"
      22              : #include "coretypes.h"
      23              : #include "backend.h"
      24              : #include "target.h"
      25              : #include "rtl.h"
      26              : #include "tree.h"
      27              : #include "cfghooks.h"
      28              : #include "df.h"
      29              : #include "memmodel.h"
      30              : #include "tm_p.h"
      31              : #include "expmed.h"
      32              : #include "optabs.h"
      33              : #include "regs.h"
      34              : #include "emit-rtl.h"
      35              : #include "recog.h"
      36              : 
      37              : #include "cfgrtl.h"
      38              : #include "cfganal.h"
      39              : #include "cfgcleanup.h"
      40              : #include "expr.h"
      41              : #include "output.h"
      42              : #include "cfgloop.h"
      43              : #include "tree-pass.h"
      44              : #include "dbgcnt.h"
      45              : #include "shrink-wrap.h"
      46              : #include "rtl-iter.h"
      47              : #include "ifcvt.h"
      48              : 
      49              : #ifndef MAX_CONDITIONAL_EXECUTE
      50              : #define MAX_CONDITIONAL_EXECUTE \
      51              :   (BRANCH_COST (optimize_function_for_speed_p (cfun), false) \
      52              :    + 1)
      53              : #endif
      54              : 
      55              : #define IFCVT_MULTIPLE_DUMPS 1
      56              : 
      57              : #define NULL_BLOCK      ((basic_block) NULL)
      58              : 
      59              : /* True if after combine pass.  */
      60              : static bool ifcvt_after_combine;
      61              : 
      62              : /* True if the target has the cbranchcc4 optab.  */
      63              : static bool have_cbranchcc4;
      64              : 
      65              : /* # of IF-THEN or IF-THEN-ELSE blocks we looked at  */
      66              : static int num_possible_if_blocks;
      67              : 
      68              : /* # of IF-THEN or IF-THEN-ELSE blocks were converted to conditional
      69              :    execution.  */
      70              : static int num_updated_if_blocks;
      71              : 
      72              : /* # of changes made.  */
      73              : static int num_true_changes;
      74              : 
      75              : /* Whether conditional execution changes were made.  */
      76              : static bool cond_exec_changed_p;
      77              : 
      78              : /* Forward references.  */
      79              : static int count_bb_insns (const_basic_block);
      80              : static bool cheap_bb_rtx_cost_p (const_basic_block, profile_probability, int);
      81              : static rtx_insn *first_active_insn (basic_block);
      82              : static rtx_insn *last_active_insn (basic_block, bool);
      83              : static rtx_insn *find_active_insn_before (basic_block, rtx_insn *);
      84              : static rtx_insn *find_active_insn_after (basic_block, rtx_insn *);
      85              : static basic_block block_fallthru (basic_block);
      86              : static rtx cond_exec_get_condition (rtx_insn *, bool);
      87              : static rtx noce_get_condition (rtx_insn *, rtx_insn **, bool);
      88              : static bool noce_operand_ok (const_rtx);
      89              : static void merge_if_block (ce_if_block *);
      90              : static bool find_cond_trap (basic_block, edge, edge);
      91              : static basic_block find_if_header (basic_block, int);
      92              : static int block_jumps_and_fallthru (basic_block, basic_block);
      93              : static bool noce_find_if_block (basic_block, edge, edge, int);
      94              : static bool cond_exec_find_if_block (ce_if_block *);
      95              : static bool find_if_case_1 (basic_block, edge, edge);
      96              : static bool find_if_case_2 (basic_block, edge, edge);
      97              : static bool dead_or_predicable (basic_block, basic_block, basic_block,
      98              :                                 edge, bool);
      99              : static void noce_emit_move_insn (rtx, rtx);
     100              : static rtx_insn *block_has_only_trap (basic_block);
     101              : static void init_noce_multiple_sets_info (basic_block,
     102              :   auto_delete_vec<noce_multiple_sets_info> &);
     103              : static bool noce_convert_multiple_sets_1 (struct noce_if_info *,
     104              :   auto_delete_vec<noce_multiple_sets_info> &, int *, bool *);
     105              : 
     106              : /* Count the number of non-jump active insns in BB.  */
     107              : 
     108              : static int
     109            0 : count_bb_insns (const_basic_block bb)
     110              : {
     111            0 :   int count = 0;
     112            0 :   rtx_insn *insn = BB_HEAD (bb);
     113              : 
     114            0 :   while (1)
     115              :     {
     116            0 :       if (active_insn_p (insn) && !JUMP_P (insn))
     117            0 :         count++;
     118              : 
     119            0 :       if (insn == BB_END (bb))
     120              :         break;
     121            0 :       insn = NEXT_INSN (insn);
     122              :     }
     123              : 
     124            0 :   return count;
     125              : }
     126              : 
     127              : /* Determine whether the total insn_cost on non-jump insns in
     128              :    basic block BB is less than MAX_COST.  This function returns
     129              :    false if the cost of any instruction could not be estimated.
     130              : 
     131              :    The cost of the non-jump insns in BB is scaled by REG_BR_PROB_BASE
     132              :    as those insns are being speculated.  MAX_COST is scaled with SCALE
     133              :    plus a small fudge factor.  */
     134              : 
     135              : static bool
     136      2979768 : cheap_bb_rtx_cost_p (const_basic_block bb,
     137              :                      profile_probability prob, int max_cost)
     138              : {
     139      2979768 :   int count = 0;
     140      2979768 :   rtx_insn *insn = BB_HEAD (bb);
     141      2979768 :   bool speed = optimize_bb_for_speed_p (bb);
     142      2979768 :   int scale = prob.initialized_p () ? prob.to_reg_br_prob_base ()
     143              :               : REG_BR_PROB_BASE;
     144              : 
     145              :   /* Set scale to REG_BR_PROB_BASE to void the identical scaling
     146              :      applied to insn_cost when optimizing for size.  Only do
     147              :      this after combine because if-conversion might interfere with
     148              :      passes before combine.
     149              : 
     150              :      Use optimize_function_for_speed_p instead of the pre-defined
     151              :      variable speed to make sure it is set to same value for all
     152              :      basic blocks in one if-conversion transformation.  */
     153      2979768 :   if (!optimize_function_for_speed_p (cfun) && ifcvt_after_combine)
     154              :     scale = REG_BR_PROB_BASE;
     155              :   /* Our branch probability/scaling factors are just estimates and don't
     156              :      account for cases where we can get speculation for free and other
     157              :      secondary benefits.  So we fudge the scale factor to make speculating
     158              :      appear a little more profitable when optimizing for performance.  */
     159              :   else
     160      2926137 :     scale += REG_BR_PROB_BASE / 8;
     161              : 
     162              : 
     163      2979768 :   max_cost *= scale;
     164              : 
     165     12001123 :   while (1)
     166              :     {
     167     14980891 :       if (NONJUMP_INSN_P (insn))
     168              :         {
     169              :           /* Inline-asm's cost is not very estimatable.
     170              :              It could be a costly instruction but the
     171              :              estimate would be the same as a non costly
     172              :              instruction.  */
     173      4457410 :           if (asm_noperands (PATTERN (insn)) >= 0)
     174              :             return false;
     175              : 
     176      4454658 :           int cost = insn_cost (insn, speed) * REG_BR_PROB_BASE;
     177      4454658 :           if (cost == 0)
     178              :             return false;
     179              : 
     180              :           /* If this instruction is the load or set of a "stack" register,
     181              :              such as a floating point register on x87, then the cost of
     182              :              speculatively executing this insn may need to include
     183              :              the additional cost of popping its result off of the
     184              :              register stack.  Unfortunately, correctly recognizing and
     185              :              accounting for this additional overhead is tricky, so for
     186              :              now we simply prohibit such speculative execution.  */
     187              : #ifdef STACK_REGS
     188      4405130 :           {
     189      4405130 :             rtx set = single_set (insn);
     190      4405130 :             if (set && STACK_REG_P (SET_DEST (set)))
     191              :               return false;
     192              :           }
     193              : #endif
     194              : 
     195      4401360 :           count += cost;
     196      4401360 :           if (count >= max_cost)
     197              :             return false;
     198              :         }
     199     10523481 :       else if (CALL_P (insn))
     200              :         return false;
     201              : 
     202     12597117 :       if (insn == BB_END (bb))
     203              :         break;
     204     12001123 :       insn = NEXT_INSN (insn);
     205     12001123 :     }
     206              : 
     207              :   return true;
     208              : }
     209              : 
     210              : /* Return the first non-jump active insn in the basic block.  */
     211              : 
     212              : static rtx_insn *
     213      1549505 : first_active_insn (basic_block bb)
     214              : {
     215      1549505 :   rtx_insn *insn = BB_HEAD (bb);
     216              : 
     217      1549505 :   if (LABEL_P (insn))
     218              :     {
     219       293000 :       if (insn == BB_END (bb))
     220              :         return NULL;
     221       293000 :       insn = NEXT_INSN (insn);
     222              :     }
     223              : 
     224      4909260 :   while (NOTE_P (insn) || DEBUG_INSN_P (insn))
     225              :     {
     226      3359755 :       if (insn == BB_END (bb))
     227              :         return NULL;
     228      3359755 :       insn = NEXT_INSN (insn);
     229              :     }
     230              : 
     231      1549505 :   if (JUMP_P (insn))
     232              :     return NULL;
     233              : 
     234              :   return insn;
     235              : }
     236              : 
     237              : /* Return the last non-jump active (non-jump) insn in the basic block.  */
     238              : 
     239              : static rtx_insn *
     240      2564950 : last_active_insn (basic_block bb, bool skip_use_p)
     241              : {
     242      2564950 :   rtx_insn *insn = BB_END (bb);
     243      2564950 :   rtx_insn *head = BB_HEAD (bb);
     244              : 
     245      2564950 :   while (NOTE_P (insn)
     246              :          || JUMP_P (insn)
     247              :          || DEBUG_INSN_P (insn)
     248      5981905 :          || (skip_use_p
     249            0 :              && NONJUMP_INSN_P (insn)
     250            0 :              && GET_CODE (PATTERN (insn)) == USE))
     251              :     {
     252      3417106 :       if (insn == head)
     253              :         return NULL;
     254      3416955 :       insn = PREV_INSN (insn);
     255              :     }
     256              : 
     257      2564799 :   if (LABEL_P (insn))
     258           72 :     return NULL;
     259              : 
     260              :   return insn;
     261              : }
     262              : 
     263              : /* Return the active insn before INSN inside basic block CURR_BB. */
     264              : 
     265              : static rtx_insn *
     266            0 : find_active_insn_before (basic_block curr_bb, rtx_insn *insn)
     267              : {
     268            0 :   if (!insn || insn == BB_HEAD (curr_bb))
     269              :     return NULL;
     270              : 
     271            0 :   while ((insn = PREV_INSN (insn)) != NULL_RTX)
     272              :     {
     273            0 :       if (NONJUMP_INSN_P (insn) || JUMP_P (insn) || CALL_P (insn))
     274              :         break;
     275              : 
     276              :       /* No other active insn all the way to the start of the basic block. */
     277            0 :       if (insn == BB_HEAD (curr_bb))
     278              :         return NULL;
     279              :     }
     280              : 
     281              :   return insn;
     282              : }
     283              : 
     284              : /* Return the active insn after INSN inside basic block CURR_BB. */
     285              : 
     286              : static rtx_insn *
     287            0 : find_active_insn_after (basic_block curr_bb, rtx_insn *insn)
     288              : {
     289            0 :   if (!insn || insn == BB_END (curr_bb))
     290              :     return NULL;
     291              : 
     292            0 :   while ((insn = NEXT_INSN (insn)) != NULL_RTX)
     293              :     {
     294            0 :       if (NONJUMP_INSN_P (insn) || JUMP_P (insn) || CALL_P (insn))
     295              :         break;
     296              : 
     297              :       /* No other active insn all the way to the end of the basic block. */
     298            0 :       if (insn == BB_END (curr_bb))
     299              :         return NULL;
     300              :     }
     301              : 
     302              :   return insn;
     303              : }
     304              : 
     305              : /* Return the basic block reached by falling though the basic block BB.  */
     306              : 
     307              : static basic_block
     308            0 : block_fallthru (basic_block bb)
     309              : {
     310            0 :   edge e = find_fallthru_edge (bb->succs);
     311              : 
     312            0 :   return (e) ? e->dest : NULL_BLOCK;
     313              : }
     314              : 
     315              : /* Return true if RTXs A and B can be safely interchanged.  */
     316              : 
     317              : static bool
     318       522845 : rtx_interchangeable_p (const_rtx a, const_rtx b)
     319              : {
     320       522845 :   if (!rtx_equal_p (a, b))
     321              :     return false;
     322              : 
     323       185114 :   if (GET_CODE (a) != MEM)
     324              :     return true;
     325              : 
     326              :   /* A dead type-unsafe memory reference is legal, but a live type-unsafe memory
     327              :      reference is not.  Interchanging a dead type-unsafe memory reference with
     328              :      a live type-safe one creates a live type-unsafe memory reference, in other
     329              :      words, it makes the program illegal.
     330              :      We check here conservatively whether the two memory references have equal
     331              :      memory attributes.  */
     332              : 
     333         1888 :   return mem_attrs_eq_p (get_mem_attrs (a), get_mem_attrs (b));
     334              : }
     335              : 
     336              : 
     337              : /* Go through a bunch of insns, converting them to conditional
     338              :    execution format if possible.  Return TRUE if all of the non-note
     339              :    insns were processed.  */
     340              : 
     341              : static bool
     342            0 : cond_exec_process_insns (ce_if_block *ce_info ATTRIBUTE_UNUSED,
     343              :                          /* if block information */rtx_insn *start,
     344              :                          /* first insn to look at */rtx end,
     345              :                          /* last insn to look at */rtx test,
     346              :                          /* conditional execution test */profile_probability
     347              :                                                             prob_val,
     348              :                          /* probability of branch taken. */bool mod_ok)
     349              : {
     350            0 :   bool must_be_last = false;
     351            0 :   rtx_insn *insn;
     352            0 :   rtx xtest;
     353            0 :   rtx pattern;
     354              : 
     355            0 :   if (!start || !end)
     356              :     return false;
     357              : 
     358            0 :   for (insn = start; ; insn = NEXT_INSN (insn))
     359              :     {
     360              :       /* dwarf2out can't cope with conditional prologues.  */
     361            0 :       if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_PROLOGUE_END)
     362              :         return false;
     363              : 
     364            0 :       if (NOTE_P (insn) || DEBUG_INSN_P (insn))
     365            0 :         goto insn_done;
     366              : 
     367            0 :       gcc_assert (NONJUMP_INSN_P (insn) || CALL_P (insn));
     368              : 
     369              :       /* dwarf2out can't cope with conditional unwind info.  */
     370            0 :       if (RTX_FRAME_RELATED_P (insn))
     371              :         return false;
     372              : 
     373              :       /* Remove USE insns that get in the way.  */
     374            0 :       if (reload_completed && GET_CODE (PATTERN (insn)) == USE)
     375              :         {
     376              :           /* ??? Ug.  Actually unlinking the thing is problematic,
     377              :              given what we'd have to coordinate with our callers.  */
     378            0 :           SET_INSN_DELETED (insn);
     379            0 :           goto insn_done;
     380              :         }
     381              : 
     382              :       /* Last insn wasn't last?  */
     383            0 :       if (must_be_last)
     384              :         return false;
     385              : 
     386            0 :       if (modified_in_p (test, insn))
     387              :         {
     388            0 :           if (!mod_ok)
     389              :             return false;
     390              :           must_be_last = true;
     391              :         }
     392              : 
     393              :       /* Now build the conditional form of the instruction.  */
     394            0 :       pattern = PATTERN (insn);
     395            0 :       xtest = copy_rtx (test);
     396              : 
     397              :       /* If this is already a COND_EXEC, rewrite the test to be an AND of the
     398              :          two conditions.  */
     399            0 :       if (GET_CODE (pattern) == COND_EXEC)
     400              :         {
     401            0 :           if (GET_MODE (xtest) != GET_MODE (COND_EXEC_TEST (pattern)))
     402              :             return false;
     403              : 
     404            0 :           xtest = gen_rtx_AND (GET_MODE (xtest), xtest,
     405              :                                COND_EXEC_TEST (pattern));
     406            0 :           pattern = COND_EXEC_CODE (pattern);
     407              :         }
     408              : 
     409            0 :       pattern = gen_rtx_COND_EXEC (VOIDmode, xtest, pattern);
     410              : 
     411              :       /* If the machine needs to modify the insn being conditionally executed,
     412              :          say for example to force a constant integer operand into a temp
     413              :          register, do so here.  */
     414              : #ifdef IFCVT_MODIFY_INSN
     415              :       IFCVT_MODIFY_INSN (ce_info, pattern, insn);
     416              :       if (! pattern)
     417              :         return false;
     418              : #endif
     419              : 
     420            0 :       validate_change (insn, &PATTERN (insn), pattern, 1);
     421              : 
     422            0 :       if (CALL_P (insn) && prob_val.initialized_p ())
     423            0 :         validate_change (insn, &REG_NOTES (insn),
     424              :                          gen_rtx_INT_LIST ((machine_mode) REG_BR_PROB,
     425              :                                            prob_val.to_reg_br_prob_note (),
     426              :                                            REG_NOTES (insn)), 1);
     427              : 
     428            0 :     insn_done:
     429            0 :       if (insn == end)
     430              :         break;
     431            0 :     }
     432              : 
     433              :   return true;
     434              : }
     435              : 
     436              : /* Return the condition for a jump.  Do not do any special processing.  */
     437              : 
     438              : static rtx
     439       122168 : cond_exec_get_condition (rtx_insn *jump, bool get_reversed = false)
     440              : {
     441       122168 :   rtx test_if, cond;
     442              : 
     443       122168 :   if (any_condjump_p (jump))
     444       122168 :     test_if = SET_SRC (pc_set (jump));
     445              :   else
     446              :     return NULL_RTX;
     447       122168 :   cond = XEXP (test_if, 0);
     448              : 
     449              :   /* If this branches to JUMP_LABEL when the condition is false,
     450              :      reverse the condition.  */
     451       122168 :   if (get_reversed
     452       122168 :       || (GET_CODE (XEXP (test_if, 2)) == LABEL_REF
     453            0 :           && label_ref_label (XEXP (test_if, 2))
     454            0 :           == JUMP_LABEL (jump)))
     455              :     {
     456        61084 :       enum rtx_code rev = reversed_comparison_code (cond, jump);
     457        61084 :       if (rev == UNKNOWN)
     458              :         return NULL_RTX;
     459              : 
     460        61084 :       cond = gen_rtx_fmt_ee (rev, GET_MODE (cond), XEXP (cond, 0),
     461              :                              XEXP (cond, 1));
     462              :     }
     463              : 
     464              :   return cond;
     465              : }
     466              : 
     467              : /* Given a simple IF-THEN or IF-THEN-ELSE block, attempt to convert it
     468              :    to conditional execution.  Return TRUE if we were successful at
     469              :    converting the block.  */
     470              : 
     471              : static bool
     472            0 : cond_exec_process_if_block (ce_if_block * ce_info,
     473              :                             /* if block information */bool do_multiple_p)
     474              : {
     475            0 :   basic_block test_bb = ce_info->test_bb;    /* last test block */
     476            0 :   basic_block then_bb = ce_info->then_bb;    /* THEN */
     477            0 :   basic_block else_bb = ce_info->else_bb;    /* ELSE or NULL */
     478            0 :   rtx test_expr;                /* expression in IF_THEN_ELSE that is tested */
     479            0 :   rtx_insn *then_start;         /* first insn in THEN block */
     480            0 :   rtx_insn *then_end;           /* last insn + 1 in THEN block */
     481            0 :   rtx_insn *else_start = NULL;  /* first insn in ELSE block or NULL */
     482            0 :   rtx_insn *else_end = NULL;    /* last insn + 1 in ELSE block */
     483            0 :   int max;                      /* max # of insns to convert.  */
     484            0 :   bool then_mod_ok;             /* whether conditional mods are ok in THEN */
     485            0 :   rtx true_expr;                /* test for else block insns */
     486            0 :   rtx false_expr;               /* test for then block insns */
     487            0 :   profile_probability true_prob_val;/* probability of else block */
     488            0 :   profile_probability false_prob_val;/* probability of then block */
     489            0 :   rtx_insn *then_last_head = NULL;      /* Last match at the head of THEN */
     490            0 :   rtx_insn *else_last_head = NULL;      /* Last match at the head of ELSE */
     491            0 :   rtx_insn *then_first_tail = NULL;     /* First match at the tail of THEN */
     492            0 :   rtx_insn *else_first_tail = NULL;     /* First match at the tail of ELSE */
     493            0 :   int then_n_insns, else_n_insns, n_insns;
     494            0 :   enum rtx_code false_code;
     495            0 :   rtx note;
     496              : 
     497              :   /* If test is comprised of && or || elements, and we've failed at handling
     498              :      all of them together, just use the last test if it is the special case of
     499              :      && elements without an ELSE block.  */
     500            0 :   if (!do_multiple_p && ce_info->num_multiple_test_blocks)
     501              :     {
     502            0 :       if (else_bb || ! ce_info->and_and_p)
     503              :         return false;
     504              : 
     505            0 :       ce_info->test_bb = test_bb = ce_info->last_test_bb;
     506            0 :       ce_info->num_multiple_test_blocks = 0;
     507            0 :       ce_info->num_and_and_blocks = 0;
     508            0 :       ce_info->num_or_or_blocks = 0;
     509              :     }
     510              : 
     511              :   /* Find the conditional jump to the ELSE or JOIN part, and isolate
     512              :      the test.  */
     513            0 :   test_expr = cond_exec_get_condition (BB_END (test_bb));
     514            0 :   if (! test_expr)
     515              :     return false;
     516              : 
     517              :   /* If the conditional jump is more than just a conditional jump,
     518              :      then we cannot do conditional execution conversion on this block.  */
     519            0 :   if (! onlyjump_p (BB_END (test_bb)))
     520              :     return false;
     521              : 
     522              :   /* Collect the bounds of where we're to search, skipping any labels, jumps
     523              :      and notes at the beginning and end of the block.  Then count the total
     524              :      number of insns and see if it is small enough to convert.  */
     525            0 :   then_start = first_active_insn (then_bb);
     526            0 :   then_end = last_active_insn (then_bb, true);
     527            0 :   then_n_insns = ce_info->num_then_insns = count_bb_insns (then_bb);
     528            0 :   n_insns = then_n_insns;
     529            0 :   max = MAX_CONDITIONAL_EXECUTE;
     530              : 
     531            0 :   if (else_bb)
     532              :     {
     533            0 :       int n_matching;
     534              : 
     535            0 :       max *= 2;
     536            0 :       else_start = first_active_insn (else_bb);
     537            0 :       else_end = last_active_insn (else_bb, true);
     538            0 :       else_n_insns = ce_info->num_else_insns = count_bb_insns (else_bb);
     539            0 :       n_insns += else_n_insns;
     540              : 
     541              :       /* Look for matching sequences at the head and tail of the two blocks,
     542              :          and limit the range of insns to be converted if possible.  */
     543            0 :       n_matching = flow_find_cross_jump (then_bb, else_bb,
     544              :                                          &then_first_tail, &else_first_tail,
     545              :                                          NULL);
     546            0 :       if (then_first_tail == BB_HEAD (then_bb))
     547            0 :         then_start = then_end = NULL;
     548            0 :       if (else_first_tail == BB_HEAD (else_bb))
     549            0 :         else_start = else_end = NULL;
     550              : 
     551            0 :       if (n_matching > 0)
     552              :         {
     553            0 :           if (then_end)
     554            0 :             then_end = find_active_insn_before (then_bb, then_first_tail);
     555            0 :           if (else_end)
     556            0 :             else_end = find_active_insn_before (else_bb, else_first_tail);
     557            0 :           n_insns -= 2 * n_matching;
     558              :         }
     559              : 
     560            0 :       if (then_start
     561            0 :           && else_start
     562              :           && then_n_insns > n_matching
     563            0 :           && else_n_insns > n_matching)
     564              :         {
     565            0 :           int longest_match = MIN (then_n_insns - n_matching,
     566              :                                    else_n_insns - n_matching);
     567            0 :           n_matching
     568            0 :             = flow_find_head_matching_sequence (then_bb, else_bb,
     569              :                                                 &then_last_head,
     570              :                                                 &else_last_head,
     571              :                                                 longest_match);
     572              : 
     573            0 :           if (n_matching > 0)
     574              :             {
     575            0 :               rtx_insn *insn;
     576              : 
     577              :               /* We won't pass the insns in the head sequence to
     578              :                  cond_exec_process_insns, so we need to test them here
     579              :                  to make sure that they don't clobber the condition.  */
     580            0 :               for (insn = BB_HEAD (then_bb);
     581            0 :                    insn != NEXT_INSN (then_last_head);
     582            0 :                    insn = NEXT_INSN (insn))
     583            0 :                 if (!LABEL_P (insn) && !NOTE_P (insn)
     584            0 :                     && !DEBUG_INSN_P (insn)
     585            0 :                     && modified_in_p (test_expr, insn))
     586              :                   return false;
     587              :             }
     588              : 
     589            0 :           if (then_last_head == then_end)
     590            0 :             then_start = then_end = NULL;
     591            0 :           if (else_last_head == else_end)
     592            0 :             else_start = else_end = NULL;
     593              : 
     594            0 :           if (n_matching > 0)
     595              :             {
     596            0 :               if (then_start)
     597            0 :                 then_start = find_active_insn_after (then_bb, then_last_head);
     598            0 :               if (else_start)
     599            0 :                 else_start = find_active_insn_after (else_bb, else_last_head);
     600            0 :               n_insns -= 2 * n_matching;
     601              :             }
     602              :         }
     603              :     }
     604              : 
     605            0 :   if (n_insns > max)
     606              :     return false;
     607              : 
     608              :   /* Map test_expr/test_jump into the appropriate MD tests to use on
     609              :      the conditionally executed code.  */
     610              : 
     611            0 :   true_expr = test_expr;
     612              : 
     613            0 :   false_code = reversed_comparison_code (true_expr, BB_END (test_bb));
     614            0 :   if (false_code != UNKNOWN)
     615            0 :     false_expr = gen_rtx_fmt_ee (false_code, GET_MODE (true_expr),
     616              :                                  XEXP (true_expr, 0), XEXP (true_expr, 1));
     617              :   else
     618              :     false_expr = NULL_RTX;
     619              : 
     620              : #ifdef IFCVT_MODIFY_TESTS
     621              :   /* If the machine description needs to modify the tests, such as setting a
     622              :      conditional execution register from a comparison, it can do so here.  */
     623              :   IFCVT_MODIFY_TESTS (ce_info, true_expr, false_expr);
     624              : 
     625              :   /* See if the conversion failed.  */
     626              :   if (!true_expr || !false_expr)
     627              :     goto fail;
     628              : #endif
     629              : 
     630            0 :   note = find_reg_note (BB_END (test_bb), REG_BR_PROB, NULL_RTX);
     631            0 :   if (note)
     632              :     {
     633            0 :       true_prob_val = profile_probability::from_reg_br_prob_note (XINT (note, 0));
     634            0 :       false_prob_val = true_prob_val.invert ();
     635              :     }
     636              :   else
     637              :     {
     638              :       true_prob_val = profile_probability::uninitialized ();
     639              :       false_prob_val = profile_probability::uninitialized ();
     640              :     }
     641              : 
     642              :   /* If we have && or || tests, do them here.  These tests are in the adjacent
     643              :      blocks after the first block containing the test.  */
     644            0 :   if (ce_info->num_multiple_test_blocks > 0)
     645              :     {
     646            0 :       basic_block bb = test_bb;
     647            0 :       basic_block last_test_bb = ce_info->last_test_bb;
     648              : 
     649            0 :       if (! false_expr)
     650            0 :         goto fail;
     651              : 
     652            0 :       do
     653              :         {
     654            0 :           rtx_insn *start, *end;
     655            0 :           rtx t, f;
     656            0 :           enum rtx_code f_code;
     657              : 
     658            0 :           bb = block_fallthru (bb);
     659            0 :           start = first_active_insn (bb);
     660            0 :           end = last_active_insn (bb, true);
     661            0 :           if (start
     662            0 :               && ! cond_exec_process_insns (ce_info, start, end, false_expr,
     663              :                                             false_prob_val, false))
     664            0 :             goto fail;
     665              : 
     666              :           /* If the conditional jump is more than just a conditional jump, then
     667              :              we cannot do conditional execution conversion on this block.  */
     668            0 :           if (! onlyjump_p (BB_END (bb)))
     669            0 :             goto fail;
     670              : 
     671              :           /* Find the conditional jump and isolate the test.  */
     672            0 :           t = cond_exec_get_condition (BB_END (bb));
     673            0 :           if (! t)
     674            0 :             goto fail;
     675              : 
     676            0 :           f_code = reversed_comparison_code (t, BB_END (bb));
     677            0 :           if (f_code == UNKNOWN)
     678            0 :             goto fail;
     679              : 
     680            0 :           f = gen_rtx_fmt_ee (f_code, GET_MODE (t), XEXP (t, 0), XEXP (t, 1));
     681            0 :           if (ce_info->and_and_p)
     682              :             {
     683            0 :               t = gen_rtx_AND (GET_MODE (t), true_expr, t);
     684            0 :               f = gen_rtx_IOR (GET_MODE (t), false_expr, f);
     685              :             }
     686              :           else
     687              :             {
     688            0 :               t = gen_rtx_IOR (GET_MODE (t), true_expr, t);
     689            0 :               f = gen_rtx_AND (GET_MODE (t), false_expr, f);
     690              :             }
     691              : 
     692              :           /* If the machine description needs to modify the tests, such as
     693              :              setting a conditional execution register from a comparison, it can
     694              :              do so here.  */
     695              : #ifdef IFCVT_MODIFY_MULTIPLE_TESTS
     696              :           IFCVT_MODIFY_MULTIPLE_TESTS (ce_info, bb, t, f);
     697              : 
     698              :           /* See if the conversion failed.  */
     699              :           if (!t || !f)
     700              :             goto fail;
     701              : #endif
     702              : 
     703            0 :           true_expr = t;
     704            0 :           false_expr = f;
     705              :         }
     706            0 :       while (bb != last_test_bb);
     707              :     }
     708              : 
     709              :   /* For IF-THEN-ELSE blocks, we don't allow modifications of the test
     710              :      on then THEN block.  */
     711            0 :   then_mod_ok = (else_bb == NULL_BLOCK);
     712              : 
     713              :   /* Go through the THEN and ELSE blocks converting the insns if possible
     714              :      to conditional execution.  */
     715              : 
     716            0 :   if (then_end
     717            0 :       && (! false_expr
     718            0 :           || ! cond_exec_process_insns (ce_info, then_start, then_end,
     719              :                                         false_expr, false_prob_val,
     720              :                                         then_mod_ok)))
     721            0 :     goto fail;
     722              : 
     723            0 :   if (else_bb && else_end
     724            0 :       && ! cond_exec_process_insns (ce_info, else_start, else_end,
     725              :                                     true_expr, true_prob_val, true))
     726            0 :     goto fail;
     727              : 
     728              :   /* If we cannot apply the changes, fail.  Do not go through the normal fail
     729              :      processing, since apply_change_group will call cancel_changes.  */
     730            0 :   if (! apply_change_group ())
     731              :     {
     732              : #ifdef IFCVT_MODIFY_CANCEL
     733              :       /* Cancel any machine dependent changes.  */
     734              :       IFCVT_MODIFY_CANCEL (ce_info);
     735              : #endif
     736              :       return false;
     737              :     }
     738              : 
     739              : #ifdef IFCVT_MODIFY_FINAL
     740              :   /* Do any machine dependent final modifications.  */
     741              :   IFCVT_MODIFY_FINAL (ce_info);
     742              : #endif
     743              : 
     744              :   /* Conversion succeeded.  */
     745            0 :   if (dump_file)
     746            0 :     fprintf (dump_file, "%d insn%s converted to conditional execution.\n",
     747              :              n_insns, (n_insns == 1) ? " was" : "s were");
     748              : 
     749              :   /* Merge the blocks!  If we had matching sequences, make sure to delete one
     750              :      copy at the appropriate location first: delete the copy in the THEN branch
     751              :      for a tail sequence so that the remaining one is executed last for both
     752              :      branches, and delete the copy in the ELSE branch for a head sequence so
     753              :      that the remaining one is executed first for both branches.  */
     754            0 :   if (then_first_tail)
     755              :     {
     756            0 :       rtx_insn *from = then_first_tail;
     757            0 :       if (!INSN_P (from))
     758            0 :         from = find_active_insn_after (then_bb, from);
     759            0 :       delete_insn_chain (from, get_last_bb_insn (then_bb), false);
     760              :     }
     761            0 :   if (else_last_head)
     762            0 :     delete_insn_chain (first_active_insn (else_bb), else_last_head, false);
     763              : 
     764            0 :   merge_if_block (ce_info);
     765            0 :   cond_exec_changed_p = true;
     766            0 :   return true;
     767              : 
     768            0 :  fail:
     769              : #ifdef IFCVT_MODIFY_CANCEL
     770              :   /* Cancel any machine dependent changes.  */
     771              :   IFCVT_MODIFY_CANCEL (ce_info);
     772              : #endif
     773              : 
     774            0 :   cancel_changes (0);
     775            0 :   return false;
     776              : }
     777              : 
     778              : static rtx noce_emit_store_flag (struct noce_if_info *, rtx, bool, int);
     779              : static bool noce_try_move (struct noce_if_info *);
     780              : static bool noce_try_ifelse_collapse (struct noce_if_info *);
     781              : static bool noce_try_store_flag (struct noce_if_info *);
     782              : static bool noce_try_addcc (struct noce_if_info *);
     783              : static bool noce_try_store_flag_constants (struct noce_if_info *);
     784              : static bool noce_try_store_flag_mask (struct noce_if_info *);
     785              : static rtx noce_emit_cmove (struct noce_if_info *, rtx, enum rtx_code, rtx,
     786              :                             rtx, rtx, rtx, rtx = NULL, rtx = NULL);
     787              : static bool noce_try_cmove (struct noce_if_info *);
     788              : static bool noce_try_cmove_arith (struct noce_if_info *);
     789              : static rtx noce_get_alt_condition (struct noce_if_info *, rtx, rtx_insn **);
     790              : static bool noce_try_minmax (struct noce_if_info *);
     791              : static bool noce_try_abs (struct noce_if_info *);
     792              : static bool noce_try_sign_mask (struct noce_if_info *);
     793              : 
     794              : /* Return the comparison code for reversed condition for IF_INFO,
     795              :    or UNKNOWN if reversing the condition is not possible.  */
     796              : 
     797              : static inline enum rtx_code
     798       313440 : noce_reversed_cond_code (struct noce_if_info *if_info)
     799              : {
     800       313440 :   if (if_info->rev_cond)
     801       313440 :     return GET_CODE (if_info->rev_cond);
     802            0 :   return reversed_comparison_code (if_info->cond, if_info->jump);
     803              : }
     804              : 
     805              : /* Return true if SEQ is a good candidate as a replacement for the
     806              :    if-convertible sequence described in IF_INFO.
     807              :    This is the default implementation that targets can override
     808              :    through a target hook.  */
     809              : 
     810              : bool
     811       177360 : default_noce_conversion_profitable_p (rtx_insn *seq,
     812              :                                       struct noce_if_info *if_info)
     813              : {
     814       177360 :   bool speed_p = if_info->speed_p;
     815              : 
     816              :   /* Cost up the new sequence.  */
     817       177360 :   unsigned int cost = seq_cost (seq, speed_p);
     818              : 
     819       177360 :   if (cost <= if_info->original_cost)
     820              :     return true;
     821              : 
     822              :   /* When compiling for size, we can make a reasonably accurately guess
     823              :      at the size growth.  When compiling for speed, use the maximum.  */
     824        93521 :   return speed_p && cost <= if_info->max_seq_cost;
     825              : }
     826              : 
     827              : /* Helper function for noce_try_store_flag*.  */
     828              : 
     829              : static rtx
     830        53570 : noce_emit_store_flag (struct noce_if_info *if_info, rtx x, bool reversep,
     831              :                       int normalize)
     832              : {
     833        53570 :   rtx cond = if_info->cond;
     834        53570 :   bool cond_complex;
     835        53570 :   enum rtx_code code;
     836              : 
     837        53570 :   cond_complex = (! general_operand (XEXP (cond, 0), VOIDmode)
     838        53570 :                   || ! general_operand (XEXP (cond, 1), VOIDmode));
     839              : 
     840              :   /* If earliest == jump, or when the condition is complex, try to
     841              :      build the store_flag insn directly.  */
     842              : 
     843        53570 :   if (cond_complex)
     844              :     {
     845        23408 :       rtx set = pc_set (if_info->jump);
     846        23408 :       cond = XEXP (SET_SRC (set), 0);
     847        23408 :       if (GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
     848        23408 :           && label_ref_label (XEXP (SET_SRC (set), 2)) == JUMP_LABEL (if_info->jump))
     849            0 :         reversep = !reversep;
     850        23408 :       if (if_info->then_else_reversed)
     851        20879 :         reversep = !reversep;
     852              :     }
     853        30162 :   else if (reversep
     854        14609 :            && if_info->rev_cond
     855        14609 :            && general_operand (XEXP (if_info->rev_cond, 0), VOIDmode)
     856        44771 :            && general_operand (XEXP (if_info->rev_cond, 1), VOIDmode))
     857              :     {
     858        14609 :       cond = if_info->rev_cond;
     859        14609 :       reversep = false;
     860              :     }
     861              : 
     862        53570 :   if (reversep)
     863         4258 :     code = reversed_comparison_code (cond, if_info->jump);
     864              :   else
     865        49312 :     code = GET_CODE (cond);
     866              : 
     867        53570 :   if ((if_info->cond_earliest == if_info->jump || cond_complex)
     868        23408 :       && (normalize == 0 || STORE_FLAG_VALUE == normalize))
     869              :     {
     870        17965 :       rtx src = gen_rtx_fmt_ee (code, GET_MODE (x), XEXP (cond, 0),
     871              :                                 XEXP (cond, 1));
     872        17965 :       rtx set = gen_rtx_SET (x, src);
     873              : 
     874        17965 :       start_sequence ();
     875        17965 :       rtx_insn *insn = emit_insn (set);
     876              : 
     877        17965 :       if (recog_memoized (insn) >= 0)
     878              :         {
     879         7954 :           rtx_insn *seq = end_sequence ();
     880         7954 :           emit_insn (seq);
     881              : 
     882         7954 :           if_info->cond_earliest = if_info->jump;
     883              : 
     884         7954 :           return x;
     885              :         }
     886              : 
     887        10011 :       end_sequence ();
     888              :     }
     889              : 
     890              :   /* Don't even try if the comparison operands or the mode of X are weird.  */
     891        45616 :   if (cond_complex || !SCALAR_INT_MODE_P (GET_MODE (x)))
     892        15454 :     return NULL_RTX;
     893              : 
     894              :   /* Don't try if mode of X is more than the max fixed mode size.  */
     895        90486 :   if (known_le (MAX_FIXED_MODE_SIZE, GET_MODE_BITSIZE (GET_MODE (x))))
     896              :     return NULL_RTX;
     897              : 
     898        29489 :   return emit_store_flag (x, code, XEXP (cond, 0),
     899              :                           XEXP (cond, 1), VOIDmode,
     900        29489 :                           (code == LTU || code == LEU
     901        58978 :                            || code == GEU || code == GTU), normalize);
     902              : }
     903              : 
     904              : /* Return true if X can be safely forced into a register by copy_to_mode_reg
     905              :    / force_operand.  */
     906              : 
     907              : static bool
     908      1761041 : noce_can_force_operand (rtx x)
     909              : {
     910      1761041 :   if (general_operand (x, VOIDmode))
     911              :     return true;
     912       388105 :   if (SUBREG_P (x))
     913              :     {
     914          363 :       if (!noce_can_force_operand (SUBREG_REG (x)))
     915              :         return false;
     916              :       return true;
     917              :     }
     918       387742 :   if (ARITHMETIC_P (x))
     919              :     {
     920       329569 :       if (!noce_can_force_operand (XEXP (x, 0))
     921       329569 :           || !noce_can_force_operand (XEXP (x, 1)))
     922         4051 :         return false;
     923       325518 :       switch (GET_CODE (x))
     924              :         {
     925              :         case MULT:
     926              :         case MOD:
     927              :         case UDIV:
     928              :         case UMOD:
     929              :           return true;
     930          487 :         case DIV:
     931          487 :           if (INTEGRAL_MODE_P (GET_MODE (x)))
     932              :             return true;
     933              :           /* FALLTHRU */
     934       317612 :         default:
     935       317612 :           auto optab = code_to_optab (GET_CODE (x));
     936       317612 :           if (!optab)
     937              :             return false;
     938       315520 :           return optab_handler (optab, GET_MODE (x));
     939              :         }
     940              :     }
     941        58173 :   if (UNARY_P (x))
     942              :     {
     943        51294 :       if (!noce_can_force_operand (XEXP (x, 0)))
     944              :         return false;
     945        51282 :       switch (GET_CODE (x))
     946              :         {
     947              :         case ZERO_EXTEND:
     948              :         case SIGN_EXTEND:
     949              :         case TRUNCATE:
     950              :         case FLOAT_EXTEND:
     951              :         case FLOAT_TRUNCATE:
     952              :         case FIX:
     953              :         case UNSIGNED_FIX:
     954              :         case FLOAT:
     955              :         case UNSIGNED_FLOAT:
     956              :           return true;
     957         5371 :         default:
     958         5371 :           auto optab = code_to_optab (GET_CODE (x));
     959         5371 :           if (!optab)
     960              :             return false;
     961         5371 :           return optab_handler (optab, GET_MODE (x));
     962              :         }
     963              :     }
     964              :   return false;
     965              : }
     966              : 
     967              : /* Emit instruction to move an rtx, possibly into STRICT_LOW_PART.
     968              :    X is the destination/target and Y is the value to copy.  */
     969              : 
     970              : static void
     971       112367 : noce_emit_move_insn (rtx x, rtx y)
     972              : {
     973       112367 :   machine_mode outmode;
     974       112367 :   rtx outer, inner;
     975       112367 :   poly_int64 bitpos;
     976              : 
     977       112367 :   if (GET_CODE (x) != STRICT_LOW_PART)
     978              :     {
     979       112367 :       rtx_insn *seq, *insn;
     980       112367 :       rtx target;
     981       112367 :       optab ot;
     982              : 
     983       112367 :       start_sequence ();
     984              :       /* Check that the SET_SRC is reasonable before calling emit_move_insn,
     985              :          otherwise construct a suitable SET pattern ourselves.  */
     986       112447 :       insn = (OBJECT_P (y) || CONSTANT_P (y) || GET_CODE (y) == SUBREG)
     987       112447 :              ? emit_move_insn (x, y)
     988        90527 :              : emit_insn (gen_rtx_SET (x, y));
     989       112367 :       seq = end_sequence ();
     990              : 
     991       112367 :       if (recog_memoized (insn) <= 0)
     992              :         {
     993        54339 :           if (GET_CODE (x) == ZERO_EXTRACT)
     994              :             {
     995            0 :               rtx op = XEXP (x, 0);
     996            0 :               unsigned HOST_WIDE_INT size = INTVAL (XEXP (x, 1));
     997            0 :               unsigned HOST_WIDE_INT start = INTVAL (XEXP (x, 2));
     998              : 
     999              :               /* store_bit_field expects START to be relative to
    1000              :                  BYTES_BIG_ENDIAN and adjusts this value for machines with
    1001              :                  BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN.  In order to be able to
    1002              :                  invoke store_bit_field again it is necessary to have the START
    1003              :                  value from the first call.  */
    1004            0 :               if (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
    1005              :                 {
    1006              :                   if (MEM_P (op))
    1007              :                     start = BITS_PER_UNIT - start - size;
    1008              :                   else
    1009              :                     {
    1010              :                       gcc_assert (REG_P (op));
    1011              :                       start = BITS_PER_WORD - start - size;
    1012              :                     }
    1013              :                 }
    1014              : 
    1015            0 :               gcc_assert (start < (MEM_P (op) ? BITS_PER_UNIT : BITS_PER_WORD));
    1016            0 :               store_bit_field (op, size, start, 0, 0, GET_MODE (x), y, false,
    1017              :                                false);
    1018            0 :               return;
    1019              :             }
    1020              : 
    1021        54339 :           switch (GET_RTX_CLASS (GET_CODE (y)))
    1022              :             {
    1023          930 :             case RTX_UNARY:
    1024          930 :               ot = code_to_optab (GET_CODE (y));
    1025          930 :               if (ot && noce_can_force_operand (XEXP (y, 0)))
    1026              :                 {
    1027          776 :                   start_sequence ();
    1028          776 :                   target = expand_unop (GET_MODE (y), ot, XEXP (y, 0), x, 0);
    1029          776 :                   if (target != NULL_RTX)
    1030              :                     {
    1031          776 :                       if (target != x)
    1032            0 :                         emit_move_insn (x, target);
    1033          776 :                       seq = get_insns ();
    1034              :                     }
    1035          776 :                   end_sequence ();
    1036              :                 }
    1037              :               break;
    1038              : 
    1039        22849 :             case RTX_BIN_ARITH:
    1040        22849 :             case RTX_COMM_ARITH:
    1041        22849 :               ot = code_to_optab (GET_CODE (y));
    1042        22849 :               if (ot
    1043        22849 :                   && noce_can_force_operand (XEXP (y, 0))
    1044        45698 :                   && noce_can_force_operand (XEXP (y, 1)))
    1045              :                 {
    1046        22849 :                   start_sequence ();
    1047        22849 :                   target = expand_binop (GET_MODE (y), ot,
    1048              :                                          XEXP (y, 0), XEXP (y, 1),
    1049              :                                          x, 0, OPTAB_DIRECT);
    1050        22849 :                   if (target != NULL_RTX)
    1051              :                     {
    1052        22821 :                       if (target != x)
    1053            0 :                           emit_move_insn (x, target);
    1054        22821 :                       seq = get_insns ();
    1055              :                     }
    1056        22849 :                   end_sequence ();
    1057              :                 }
    1058              :               break;
    1059              : 
    1060              :             default:
    1061              :               break;
    1062              :             }
    1063              :         }
    1064              : 
    1065       112367 :       emit_insn (seq);
    1066       112367 :       return;
    1067              :     }
    1068              : 
    1069            0 :   outer = XEXP (x, 0);
    1070            0 :   inner = XEXP (outer, 0);
    1071            0 :   outmode = GET_MODE (outer);
    1072            0 :   bitpos = SUBREG_BYTE (outer) * BITS_PER_UNIT;
    1073            0 :   store_bit_field (inner, GET_MODE_BITSIZE (outmode), bitpos,
    1074              :                    0, 0, outmode, y, false, false);
    1075              : }
    1076              : 
    1077              : /* Return the CC reg if it is used in COND.  */
    1078              : 
    1079              : static rtx
    1080      4157470 : cc_in_cond (rtx cond)
    1081              : {
    1082      4157470 :   if (have_cbranchcc4 && cond
    1083      4157470 :       && GET_MODE_CLASS (GET_MODE (XEXP (cond, 0))) == MODE_CC)
    1084       118674 :     return XEXP (cond, 0);
    1085              : 
    1086              :   return NULL_RTX;
    1087              : }
    1088              : 
    1089              : /* Return sequence of instructions generated by if conversion.  This
    1090              :    function calls end_sequence() to end the current stream, ensures
    1091              :    that the instructions are unshared, recognizable non-jump insns.
    1092              :    On failure, this function returns a NULL_RTX.  */
    1093              : 
    1094              : static rtx_insn *
    1095       246904 : end_ifcvt_sequence (struct noce_if_info *if_info)
    1096              : {
    1097       246904 :   rtx_insn *insn;
    1098       246904 :   rtx_insn *seq = get_insns ();
    1099       246904 :   rtx cc = cc_in_cond (if_info->cond);
    1100              : 
    1101       246904 :   set_used_flags (if_info->x);
    1102       246904 :   set_used_flags (if_info->cond);
    1103       246904 :   set_used_flags (if_info->a);
    1104       246904 :   set_used_flags (if_info->b);
    1105              : 
    1106      1308435 :   for (insn = seq; insn; insn = NEXT_INSN (insn))
    1107       814627 :     set_used_flags (insn);
    1108              : 
    1109       246904 :   unshare_all_rtl_in_chain (seq);
    1110       246904 :   end_sequence ();
    1111              : 
    1112              :   /* Make sure that all of the instructions emitted are recognizable,
    1113              :      and that we haven't introduced a new jump instruction.
    1114              :      As an exercise for the reader, build a general mechanism that
    1115              :      allows proper placement of required clobbers.  */
    1116      1277239 :   for (insn = seq; insn; insn = NEXT_INSN (insn))
    1117       814208 :     if (JUMP_P (insn)
    1118       814208 :         || recog_memoized (insn) == -1
    1119              :            /* Make sure new generated code does not clobber CC.  */
    1120      1597717 :         || (cc && set_of (cc, insn)))
    1121        30777 :       return NULL;
    1122              : 
    1123              :   return seq;
    1124              : }
    1125              : 
    1126              : /* Return true iff the then and else basic block (if it exists)
    1127              :    consist of a single simple set instruction.  */
    1128              : 
    1129              : static bool
    1130      3019362 : noce_simple_bbs (struct noce_if_info *if_info)
    1131              : {
    1132            0 :   if (!if_info->then_simple)
    1133              :     return false;
    1134              : 
    1135      2816847 :   if (if_info->else_bb)
    1136            0 :     return if_info->else_simple;
    1137              : 
    1138              :   return true;
    1139              : }
    1140              : 
    1141              : /* Convert "if (a != b) x = a; else x = b" into "x = a" and
    1142              :    "if (a == b) x = a; else x = b" into "x = b".  */
    1143              : 
    1144              : static bool
    1145       270754 : noce_try_move (struct noce_if_info *if_info)
    1146              : {
    1147       270754 :   rtx cond = if_info->cond;
    1148       270754 :   enum rtx_code code = GET_CODE (cond);
    1149       270754 :   rtx y;
    1150       270754 :   rtx_insn *seq;
    1151              : 
    1152       270754 :   if (code != NE && code != EQ)
    1153              :     return false;
    1154              : 
    1155       543970 :   if (!noce_simple_bbs (if_info))
    1156              :     return false;
    1157              : 
    1158              :   /* This optimization isn't valid if either A or B could be a NaN
    1159              :      or a signed zero.  */
    1160       202718 :   if (HONOR_NANS (if_info->x)
    1161       202718 :       || HONOR_SIGNED_ZEROS (if_info->x))
    1162        52781 :     return false;
    1163              : 
    1164              :   /* Check whether the operands of the comparison are A and in
    1165              :      either order.  */
    1166       149937 :   if ((rtx_equal_p (if_info->a, XEXP (cond, 0))
    1167         2138 :        && rtx_equal_p (if_info->b, XEXP (cond, 1)))
    1168       152065 :       || (rtx_equal_p (if_info->a, XEXP (cond, 1))
    1169        15268 :           && rtx_equal_p (if_info->b, XEXP (cond, 0))))
    1170              :     {
    1171           15 :       if (!rtx_interchangeable_p (if_info->a, if_info->b))
    1172              :         return false;
    1173              : 
    1174            0 :       y = (code == EQ) ? if_info->a : if_info->b;
    1175              : 
    1176              :       /* Avoid generating the move if the source is the destination.  */
    1177            0 :       if (! rtx_equal_p (if_info->x, y))
    1178              :         {
    1179            0 :           start_sequence ();
    1180            0 :           noce_emit_move_insn (if_info->x, y);
    1181            0 :           seq = end_ifcvt_sequence (if_info);
    1182            0 :           if (!seq)
    1183              :             return false;
    1184              : 
    1185            0 :           emit_insn_before_setloc (seq, if_info->jump,
    1186            0 :                                    INSN_LOCATION (if_info->insn_a));
    1187              :         }
    1188            0 :       if_info->transform_name = "noce_try_move";
    1189            0 :       return true;
    1190              :     }
    1191              :   return false;
    1192              : }
    1193              : 
    1194              : /* If a sign bit test is selecting across constants, we may be able
    1195              :    to generate efficient code utilizing the -1/0 result of a sign
    1196              :    bit splat idiom. 
    1197              : 
    1198              :    Do this before trying the generalized conditional move as these
    1199              :    (when applicable) are hopefully faster than a conditional move.  */
    1200              : 
    1201              : static bool
    1202       226244 : noce_try_sign_bit_splat (struct noce_if_info *if_info)
    1203              : {
    1204       226244 :   rtx cond = if_info->cond;
    1205       226244 :   enum rtx_code code = GET_CODE (cond);
    1206              : 
    1207              :   /* We're looking for sign bit tests, so only a few cases are
    1208              :      interesting.  LT/GE 0 LE/GT -1.  */
    1209       226244 :   if (((code == LT || code == GE)
    1210        10253 :        && XEXP (cond, 1) == CONST0_RTX (GET_MODE (cond)))
    1211       223857 :       || ((code == LE || code == GT)
    1212        11589 :           && XEXP (cond, 1) == CONSTM1_RTX (GET_MODE (cond))))
    1213              :     ;
    1214              :   else
    1215              :     return false;
    1216              : 
    1217              :   /* It would be good if this could be extended since constant synthesis
    1218              :      on some platforms will result in blocks which fail this test.  */
    1219       233786 :   if (!noce_simple_bbs (if_info))
    1220              :     return false;
    1221              : 
    1222              :   /* Only try this for constants in the true/false arms and a REG
    1223              :      destination.   We could select between 0 and a REG pretty
    1224              :      easily with a logical AND.  */
    1225         6050 :   if (!CONST_INT_P (if_info->a)
    1226         1883 :       || !CONST_INT_P (if_info->b)
    1227          604 :       || !REG_P (if_info->x))
    1228              :     return false;
    1229              : 
    1230          604 :   machine_mode mode = GET_MODE (if_info->x);
    1231              : 
    1232              :   /* If the mode of the destination does not match the mode of
    1233              :      the value we're testing, then this optimization is not valid.  */
    1234          604 :   if (mode != GET_MODE (XEXP (cond, 0)))
    1235              :     return false;
    1236              : 
    1237          231 :   HOST_WIDE_INT val_a = INTVAL (if_info->a);
    1238          231 :   HOST_WIDE_INT val_b = INTVAL (if_info->b);
    1239              : 
    1240          231 :   rtx_insn *seq;
    1241          231 :   start_sequence ();
    1242              : 
    1243              :   /* We're testing the sign bit of this operand.  */
    1244          231 :   rtx condop = XEXP (cond, 0);
    1245              : 
    1246              :   /* To splat the sign bit we arithmetically shift the
    1247              :      input value right by the size of the object - 1 bits. 
    1248              : 
    1249              :      Note some targets do not have strong shifters, but do have
    1250              :      alternative ways to generate the sign bit splat.  The
    1251              :      profitability test when we end the sequence should reject
    1252              :      cases when the branchy sequence is better.  */
    1253          231 :   int splat_count = GET_MODE_BITSIZE (GET_MODE (condop)).to_constant () - 1;
    1254          231 :   rtx splat = GEN_INT (splat_count);
    1255              : 
    1256          231 :   rtx temp;
    1257          231 :   temp = expand_simple_binop (GET_MODE (XEXP (cond, 0)), ASHIFTRT,
    1258              :                               XEXP (cond, 0), splat, NULL_RTX,
    1259              :                               false, OPTAB_WIDEN);
    1260          231 :   if (!temp)
    1261            0 :     goto fail;
    1262              : 
    1263              :   /* IOR of anything with -1 still results in -1.  So we can
    1264              :      IOR the other operand to generate a select between -1 and
    1265              :      an arbitrary constant.  */
    1266          231 :   if (val_a == -1)
    1267              :     {
    1268           64 :       if (code == LT || code == LE)
    1269              :         {
    1270            2 :           temp = expand_simple_unop (mode, NOT, temp, NULL_RTX, true);
    1271            2 :           if (!temp)
    1272            0 :             goto fail;
    1273              :         }
    1274              : 
    1275           64 :       temp = expand_simple_binop (mode, IOR, temp, GEN_INT (val_b),
    1276              :                                   if_info->x, false, OPTAB_WIDEN);
    1277              :     }
    1278              :   /* AND of anything with 0 is still zero.  So we can AND
    1279              :      with the -1 operand with the a constant to select
    1280              :      between the constant and zero.  */
    1281          167 :   else if (val_b == 0)
    1282              :     {
    1283            0 :       if (code == LT || code == LE)
    1284              :         {
    1285            0 :           temp = expand_simple_unop (mode, NOT, temp, NULL_RTX, true);
    1286            0 :           if (!temp)
    1287            0 :             goto fail;
    1288              :         }
    1289              : 
    1290              :       /* Since we know the value is currenly -1 or 0, some constants may
    1291              :          be more easily handled by shifting the value again.  A right
    1292              :          logical shift constructs 2^n-1 constants a left shift constructs
    1293              :          ~(2^n-1) constants.  Given some targets don't have efficient
    1294              :          shifts, generate the obvious RTL for both forms and select the
    1295              :          one with smaller cost.  */
    1296            0 :       rtx and_form = gen_rtx_AND (mode, temp, GEN_INT (val_a));
    1297            0 :       rtx shift_left = gen_rtx_ASHIFT (mode, temp, GEN_INT (ctz_hwi (val_a)));
    1298            0 :       HOST_WIDE_INT rshift_count
    1299            0 :         = (clz_hwi (val_a) & (GET_MODE_PRECISION (mode).to_constant() - 1));
    1300            0 :       rtx shift_right = gen_rtx_LSHIFTRT (mode, temp, GEN_INT (rshift_count));
    1301            0 :       bool speed_p = optimize_insn_for_speed_p ();
    1302            0 :       if (exact_log2 (val_a + 1) >= 0
    1303            0 :           && (rtx_cost (shift_right, mode, SET, 1, speed_p)
    1304            0 :               < rtx_cost (and_form, mode, SET, 1, speed_p)))
    1305            0 :         temp = expand_simple_binop (mode, LSHIFTRT, temp,
    1306              :                                     GEN_INT (rshift_count),
    1307              :                                     if_info->x, false, OPTAB_WIDEN);
    1308            0 :       else if (exact_log2 (~val_a + 1) >= 0
    1309            0 :                && (rtx_cost (shift_left, mode, SET, 1, speed_p)
    1310            0 :                    < rtx_cost (and_form, mode, SET, 1, speed_p)))
    1311            0 :         temp = expand_simple_binop (mode, ASHIFT, temp,
    1312            0 :                                     GEN_INT (ctz_hwi (val_a)),
    1313              :                                     if_info->x, false, OPTAB_WIDEN);
    1314              :       else
    1315            0 :         temp = expand_simple_binop (mode, AND, temp, GEN_INT (val_a),
    1316              :                                     if_info->x, false, OPTAB_WIDEN);
    1317              :     }
    1318              :   /* Same cases, but with the test or arms swapped.  These
    1319              :      can be realized as well, though it typically costs
    1320              :      an extra instruction.  */
    1321          167 :   else if (val_b == -1)
    1322              :     {
    1323           46 :       if (code != LT && code != LE)
    1324              :         {
    1325            2 :           temp = expand_simple_unop (mode, NOT, temp, NULL_RTX, true);
    1326            2 :           if (!temp)
    1327            0 :             goto fail;
    1328              :         }
    1329              : 
    1330           46 :       temp = expand_simple_binop (mode, IOR, temp, GEN_INT (val_a),
    1331              :                                   if_info->x, false, OPTAB_WIDEN);
    1332              :     }
    1333          121 :   else if (val_a == 0)
    1334              :     {
    1335           78 :       if (code != LT && code != LE)
    1336              :         {
    1337            9 :           temp = expand_simple_unop (mode, NOT, temp, NULL_RTX, true);
    1338            9 :           if (!temp)
    1339            0 :             goto fail;
    1340              :         }
    1341              : 
    1342              :       /* Since we know the value is currenly -1 or 0, some constants may
    1343              :          be more easily handled by shifting the value again.  A right
    1344              :          logical shift constructs 2^n-1 constants a left shift constructs
    1345              :          ~(2^n-1) constants.  Given some targets don't have efficient
    1346              :          shifts, generate the obvious RTL for both forms and select the
    1347              :          one with smaller cost.  */
    1348           78 :       rtx and_form = gen_rtx_AND (mode, temp, GEN_INT (val_b));
    1349           78 :       rtx shift_left = gen_rtx_ASHIFT (mode, temp, GEN_INT (ctz_hwi (val_b)));
    1350           78 :       HOST_WIDE_INT rshift_count
    1351           78 :         = (clz_hwi (val_b) & (GET_MODE_PRECISION (mode).to_constant() - 1));
    1352           78 :       rtx shift_right = gen_rtx_LSHIFTRT (mode, temp, GEN_INT (rshift_count));
    1353           78 :       bool speed_p = optimize_insn_for_speed_p ();
    1354           78 :       if (exact_log2 (val_b + 1) >= 0
    1355           50 :           && (rtx_cost (shift_right, mode, SET, 1, speed_p)
    1356           25 :               < rtx_cost (and_form, mode, SET, 1, speed_p)))
    1357            3 :         temp = expand_simple_binop (mode, LSHIFTRT, temp,
    1358              :                                     GEN_INT (rshift_count),
    1359              :                                     if_info->x, false, OPTAB_WIDEN);
    1360           75 :       else if (exact_log2 (~val_b + 1) >= 0
    1361            0 :                && (rtx_cost (shift_left, mode, SET, 1, speed_p)
    1362            0 :                    < rtx_cost (and_form, mode, SET, 1, speed_p)))
    1363            0 :         temp = expand_simple_binop (mode, ASHIFT, temp,
    1364            0 :                                     GEN_INT (ctz_hwi (val_b)),
    1365              :                                     if_info->x, false, OPTAB_WIDEN);
    1366              :       else
    1367           75 :         temp = expand_simple_binop (mode, AND, temp, GEN_INT (val_b),
    1368              :                                     if_info->x, false, OPTAB_WIDEN);
    1369              :     }
    1370              :   /* Nothing worked.  */
    1371              :   else
    1372              :     temp = NULL_RTX;
    1373              : 
    1374          188 :   if (!temp)
    1375           43 :     goto fail;
    1376              : 
    1377              :   /* Move into the final destination if the value wasn't
    1378              :      constructed there.  */
    1379          188 :   if (if_info->x != temp)
    1380            0 :     emit_move_insn (if_info->x, temp);
    1381              : 
    1382              :   /* This ends the sequence and tests the cost model.  */
    1383          188 :   seq = end_ifcvt_sequence (if_info);
    1384          188 :   if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
    1385            0 :     return false;
    1386              : 
    1387              :   /* Everything looks good.  Install the if-converted sequence.  */
    1388          188 :   emit_insn_before_setloc (seq, if_info->jump,
    1389          188 :                            INSN_LOCATION (if_info->insn_a));
    1390          188 :   if_info->transform_name = "splat_sign_bit_trivial";
    1391          188 :   return true;
    1392              : 
    1393           43 :  fail:
    1394           43 :   end_ifcvt_sequence (if_info);
    1395           43 :   return false;
    1396              : }
    1397              : 
    1398              : 
    1399              : /* Try forming an IF_THEN_ELSE (cond, b, a) and collapsing that
    1400              :    through simplify_rtx.  Sometimes that can eliminate the IF_THEN_ELSE.
    1401              :    If that is the case, emit the result into x.  */
    1402              : 
    1403              : static bool
    1404       270754 : noce_try_ifelse_collapse (struct noce_if_info * if_info)
    1405              : {
    1406       587762 :   if (!noce_simple_bbs (if_info))
    1407              :     return false;
    1408              : 
    1409       252768 :   machine_mode mode = GET_MODE (if_info->x);
    1410       252768 :   rtx if_then_else = simplify_gen_ternary (IF_THEN_ELSE, mode, mode,
    1411              :                                             if_info->cond, if_info->b,
    1412              :                                             if_info->a);
    1413              : 
    1414       252768 :   if (GET_CODE (if_then_else) == IF_THEN_ELSE)
    1415              :     return false;
    1416              : 
    1417        46179 :   rtx_insn *seq;
    1418        46179 :   start_sequence ();
    1419        46179 :   noce_emit_move_insn (if_info->x, if_then_else);
    1420        46179 :   seq = end_ifcvt_sequence (if_info);
    1421        46179 :   if (!seq)
    1422              :     return false;
    1423              : 
    1424        15619 :   emit_insn_before_setloc (seq, if_info->jump,
    1425        15619 :                           INSN_LOCATION (if_info->insn_a));
    1426              : 
    1427        15619 :   if_info->transform_name = "noce_try_ifelse_collapse";
    1428        15619 :   return true;
    1429              : }
    1430              : 
    1431              : 
    1432              : /* Convert "if (test) x = 1; else x = 0".
    1433              : 
    1434              :    Only try 0 and STORE_FLAG_VALUE here.  Other combinations will be
    1435              :    tried in noce_try_store_flag_constants after noce_try_cmove has had
    1436              :    a go at the conversion.  */
    1437              : 
    1438              : static bool
    1439       255135 : noce_try_store_flag (struct noce_if_info *if_info)
    1440              : {
    1441       255135 :   bool reversep;
    1442       255135 :   rtx target;
    1443       255135 :   rtx_insn *seq;
    1444              : 
    1445       532959 :   if (!noce_simple_bbs (if_info))
    1446              :     return false;
    1447              : 
    1448       237149 :   if (CONST_INT_P (if_info->b)
    1449        70122 :       && INTVAL (if_info->b) == STORE_FLAG_VALUE
    1450        13063 :       && if_info->a == const0_rtx)
    1451              :     reversep = false;
    1452       226748 :   else if (if_info->b == const0_rtx
    1453        31098 :            && CONST_INT_P (if_info->a)
    1454        20581 :            && INTVAL (if_info->a) == STORE_FLAG_VALUE
    1455       246908 :            && noce_reversed_cond_code (if_info) != UNKNOWN)
    1456              :     reversep = true;
    1457              :   else
    1458       206588 :     return false;
    1459              : 
    1460        30561 :   start_sequence ();
    1461              : 
    1462        30561 :   target = noce_emit_store_flag (if_info, if_info->x, reversep, 0);
    1463        30561 :   if (target)
    1464              :     {
    1465        25904 :       if (target != if_info->x)
    1466         2966 :         noce_emit_move_insn (if_info->x, target);
    1467              : 
    1468        25904 :       seq = end_ifcvt_sequence (if_info);
    1469        25904 :       if (! seq)
    1470              :         return false;
    1471              : 
    1472        25904 :       emit_insn_before_setloc (seq, if_info->jump,
    1473        25904 :                                INSN_LOCATION (if_info->insn_a));
    1474        25904 :       if_info->transform_name = "noce_try_store_flag";
    1475        25904 :       return true;
    1476              :     }
    1477              :   else
    1478              :     {
    1479         4657 :       end_sequence ();
    1480         4657 :       return false;
    1481              :     }
    1482              : }
    1483              : 
    1484              : 
    1485              : /* Convert "if (test) x = -A; else x = A" into
    1486              :    x = A; if (test) x = -x if the machine can do the
    1487              :    conditional negate form of this cheaply.
    1488              :    Try this before noce_try_cmove that will just load the
    1489              :    immediates into two registers and do a conditional select
    1490              :    between them.  If the target has a conditional negate or
    1491              :    conditional invert operation we can save a potentially
    1492              :    expensive constant synthesis.  */
    1493              : 
    1494              : static bool
    1495       229154 : noce_try_inverse_constants (struct noce_if_info *if_info)
    1496              : {
    1497       497297 :   if (!noce_simple_bbs (if_info))
    1498              :     return false;
    1499              : 
    1500       211168 :   if (!CONST_INT_P (if_info->a)
    1501        49231 :       || !CONST_INT_P (if_info->b)
    1502        20202 :       || !REG_P (if_info->x))
    1503              :     return false;
    1504              : 
    1505        20202 :   machine_mode mode = GET_MODE (if_info->x);
    1506              : 
    1507        20202 :   HOST_WIDE_INT val_a = INTVAL (if_info->a);
    1508        20202 :   HOST_WIDE_INT val_b = INTVAL (if_info->b);
    1509              : 
    1510        20202 :   rtx cond = if_info->cond;
    1511              : 
    1512        20202 :   rtx x = if_info->x;
    1513        20202 :   rtx target;
    1514              : 
    1515        20202 :   start_sequence ();
    1516              : 
    1517        20202 :   rtx_code code;
    1518        20202 :   if (val_b != HOST_WIDE_INT_MIN && val_a == -val_b)
    1519              :     code = NEG;
    1520        19025 :   else if (val_a == ~val_b)
    1521              :     code = NOT;
    1522              :   else
    1523              :     {
    1524        18956 :       end_sequence ();
    1525        18956 :       return false;
    1526              :     }
    1527              : 
    1528         1246 :   rtx tmp = gen_reg_rtx (mode);
    1529         1246 :   noce_emit_move_insn (tmp, if_info->a);
    1530              : 
    1531         1246 :   target = emit_conditional_neg_or_complement (x, code, mode, cond, tmp, tmp);
    1532              : 
    1533         1246 :   if (target)
    1534              :     {
    1535            0 :       rtx_insn *seq = get_insns ();
    1536              : 
    1537            0 :       if (!seq)
    1538              :         {
    1539            0 :           end_sequence ();
    1540            0 :           return false;
    1541              :         }
    1542              : 
    1543            0 :       if (target != if_info->x)
    1544            0 :         noce_emit_move_insn (if_info->x, target);
    1545              : 
    1546            0 :       seq = end_ifcvt_sequence (if_info);
    1547              : 
    1548            0 :       if (!seq)
    1549              :         return false;
    1550              : 
    1551            0 :       emit_insn_before_setloc (seq, if_info->jump,
    1552            0 :                                INSN_LOCATION (if_info->insn_a));
    1553            0 :       if_info->transform_name = "noce_try_inverse_constants";
    1554            0 :       return true;
    1555              :     }
    1556              : 
    1557         1246 :   end_sequence ();
    1558         1246 :   return false;
    1559              : }
    1560              : 
    1561              : 
    1562              : /* Convert "if (test) x = a; else x = b", for A and B constant.
    1563              :    Also allow A = y + c1, B = y + c2, with a common y between A
    1564              :    and B.  */
    1565              : 
    1566              : static bool
    1567       229154 : noce_try_store_flag_constants (struct noce_if_info *if_info)
    1568              : {
    1569       229154 :   rtx target;
    1570       229154 :   rtx_insn *seq;
    1571       229154 :   bool reversep;
    1572       229154 :   HOST_WIDE_INT itrue, ifalse, diff, tmp;
    1573       229154 :   int normalize;
    1574       229154 :   bool can_reverse;
    1575       229154 :   machine_mode mode = GET_MODE (if_info->x);
    1576       229154 :   rtx common = NULL_RTX;
    1577              : 
    1578       229154 :   rtx a = if_info->a;
    1579       229154 :   rtx b = if_info->b;
    1580              : 
    1581              :   /* Handle cases like x := test ? y + 3 : y + 4.  */
    1582       229154 :   if (GET_CODE (a) == PLUS
    1583        23434 :       && GET_CODE (b) == PLUS
    1584         1516 :       && CONST_INT_P (XEXP (a, 1))
    1585          804 :       && CONST_INT_P (XEXP (b, 1))
    1586          701 :       && rtx_equal_p (XEXP (a, 0), XEXP (b, 0))
    1587              :       /* Allow expressions that are not using the result or plain
    1588              :          registers where we handle overlap below.  */
    1589       229743 :       && (REG_P (XEXP (a, 0))
    1590           10 :           || (noce_operand_ok (XEXP (a, 0))
    1591           10 :               && ! reg_overlap_mentioned_p (if_info->x, XEXP (a, 0)))))
    1592              :     {
    1593          589 :       common = XEXP (a, 0);
    1594          589 :       a = XEXP (a, 1);
    1595          589 :       b = XEXP (b, 1);
    1596              :     }
    1597              : 
    1598       286129 :   if (!noce_simple_bbs (if_info))
    1599              :     return false;
    1600              : 
    1601       211168 :   if (CONST_INT_P (a)
    1602        49808 :       && CONST_INT_P (b))
    1603              :     {
    1604        20779 :       ifalse = INTVAL (a);
    1605        20779 :       itrue = INTVAL (b);
    1606        20779 :       bool subtract_flag_p = false;
    1607              : 
    1608        20779 :       diff = (unsigned HOST_WIDE_INT) itrue - ifalse;
    1609              :       /* Make sure we can represent the difference between the two values.  */
    1610        20779 :       if ((diff > 0)
    1611        20779 :           != ((ifalse < 0) != (itrue < 0) ? ifalse < 0 : ifalse < itrue))
    1612              :         return false;
    1613              : 
    1614        20659 :       diff = trunc_int_for_mode (diff, mode);
    1615              : 
    1616        20659 :       can_reverse = noce_reversed_cond_code (if_info) != UNKNOWN;
    1617        20659 :       reversep = false;
    1618        20659 :       if (diff == STORE_FLAG_VALUE || diff == -STORE_FLAG_VALUE)
    1619              :         {
    1620        11532 :           normalize = 0;
    1621              :           /* We could collapse these cases but it is easier to follow the
    1622              :              diff/STORE_FLAG_VALUE combinations when they are listed
    1623              :              explicitly.  */
    1624              : 
    1625              :           /* test ? 3 : 4
    1626              :              => 4 + (test != 0).  */
    1627        11532 :           if (diff < 0 && STORE_FLAG_VALUE < 0)
    1628              :               reversep = false;
    1629              :           /* test ? 4 : 3
    1630              :              => can_reverse  | 4 + (test == 0)
    1631              :                 !can_reverse | 3 - (test != 0).  */
    1632        11532 :           else if (diff > 0 && STORE_FLAG_VALUE < 0)
    1633              :             {
    1634              :               reversep = can_reverse;
    1635              :               subtract_flag_p = !can_reverse;
    1636              :               /* If we need to subtract the flag and we have PLUS-immediate
    1637              :                  A and B then it is unlikely to be beneficial to play tricks
    1638              :                  here.  */
    1639              :               if (subtract_flag_p && common)
    1640              :                 return false;
    1641              :             }
    1642              :           /* test ? 3 : 4
    1643              :              => can_reverse  | 3 + (test == 0)
    1644              :                 !can_reverse | 4 - (test != 0).  */
    1645        11532 :           else if (diff < 0 && STORE_FLAG_VALUE > 0)
    1646              :             {
    1647         5980 :               reversep = can_reverse;
    1648         5980 :               subtract_flag_p = !can_reverse;
    1649              :               /* If we need to subtract the flag and we have PLUS-immediate
    1650              :                  A and B then it is unlikely to be beneficial to play tricks
    1651              :                  here.  */
    1652         5980 :               if (subtract_flag_p && common)
    1653              :                 return false;
    1654              :             }
    1655              :           /* test ? 4 : 3
    1656              :              => 4 + (test != 0).  */
    1657              :           else if (diff > 0 && STORE_FLAG_VALUE > 0)
    1658              :             reversep = false;
    1659              :           else
    1660              :             gcc_unreachable ();
    1661              :         }
    1662              :       /* Is this (cond) ? 2^n : 0?  */
    1663          519 :       else if (ifalse == 0 && pow2p_hwi (itrue)
    1664         9127 :                && STORE_FLAG_VALUE == 1)
    1665              :         normalize = 1;
    1666              :       /* Is this (cond) ? 0 : 2^n?  */
    1667       226598 :       else if (itrue == 0 && pow2p_hwi (ifalse) && can_reverse
    1668         9122 :                && STORE_FLAG_VALUE == 1)
    1669              :         {
    1670              :           normalize = 1;
    1671              :           reversep = true;
    1672              :         }
    1673              :       /* Is this (cond) ? -1 : x?  */
    1674              :       else if (itrue == -1
    1675              :                && STORE_FLAG_VALUE == -1)
    1676              :         normalize = -1;
    1677              :       /* Is this (cond) ? x : -1?  */
    1678              :       else if (ifalse == -1 && can_reverse
    1679              :                && STORE_FLAG_VALUE == -1)
    1680              :         {
    1681              :           normalize = -1;
    1682              :           reversep = true;
    1683              :         }
    1684              :       else
    1685              :         return false;
    1686              : 
    1687         5980 :       if (reversep)
    1688              :         {
    1689         5982 :           std::swap (itrue, ifalse);
    1690         5982 :           diff = trunc_int_for_mode (-(unsigned HOST_WIDE_INT) diff, mode);
    1691              :         }
    1692              : 
    1693        11541 :       start_sequence ();
    1694              : 
    1695              :       /* If we have x := test ? x + 3 : x + 4 then move the original
    1696              :          x out of the way while we store flags.  */
    1697        11541 :       if (common && rtx_equal_p (common, if_info->x))
    1698              :         {
    1699           30 :           common = gen_reg_rtx (mode);
    1700           30 :           noce_emit_move_insn (common, if_info->x);
    1701              :         }
    1702              : 
    1703        11541 :       target = noce_emit_store_flag (if_info, if_info->x, reversep, normalize);
    1704        11541 :       if (! target)
    1705              :         {
    1706         4694 :           end_sequence ();
    1707         4694 :           return false;
    1708              :         }
    1709              : 
    1710              :       /* if (test) x = 3; else x = 4;
    1711              :          =>   x = 3 + (test == 0);  */
    1712         6847 :       if (diff == STORE_FLAG_VALUE || diff == -STORE_FLAG_VALUE)
    1713              :         {
    1714              :           /* Add the common part now.  This may allow combine to merge this
    1715              :              with the store flag operation earlier into some sort of conditional
    1716              :              increment/decrement if the target allows it.  */
    1717         6838 :           if (common)
    1718          104 :             target = expand_simple_binop (mode, PLUS,
    1719              :                                            target, common,
    1720              :                                            target, 0, OPTAB_WIDEN);
    1721              : 
    1722              :           /* Always use ifalse here.  It should have been swapped with itrue
    1723              :              when appropriate when reversep is true.  */
    1724        13676 :           target = expand_simple_binop (mode, subtract_flag_p ? MINUS : PLUS,
    1725         6838 :                                         gen_int_mode (ifalse, mode), target,
    1726              :                                         if_info->x, 0, OPTAB_WIDEN);
    1727              :         }
    1728              :       /* Other cases are not beneficial when the original A and B are PLUS
    1729              :          expressions.  */
    1730            9 :       else if (common)
    1731              :         {
    1732            0 :           end_sequence ();
    1733            0 :           return false;
    1734              :         }
    1735              :       /* if (test) x = 8; else x = 0;
    1736              :          =>   x = (test != 0) << 3;  */
    1737            9 :       else if (ifalse == 0 && (tmp = exact_log2 (itrue)) >= 0)
    1738              :         {
    1739            9 :           target = expand_simple_binop (mode, ASHIFT,
    1740              :                                         target, GEN_INT (tmp), if_info->x, 0,
    1741              :                                         OPTAB_WIDEN);
    1742              :         }
    1743              : 
    1744              :       /* if (test) x = -1; else x = b;
    1745              :          =>   x = -(test != 0) | b;  */
    1746            0 :       else if (itrue == -1)
    1747              :         {
    1748            0 :           target = expand_simple_binop (mode, IOR,
    1749            0 :                                         target, gen_int_mode (ifalse, mode),
    1750              :                                         if_info->x, 0, OPTAB_WIDEN);
    1751              :         }
    1752              :       else
    1753              :         {
    1754            0 :           end_sequence ();
    1755            0 :           return false;
    1756              :         }
    1757              : 
    1758         6847 :       if (! target)
    1759              :         {
    1760            0 :           end_sequence ();
    1761            0 :           return false;
    1762              :         }
    1763              : 
    1764         6847 :       if (target != if_info->x)
    1765            0 :         noce_emit_move_insn (if_info->x, target);
    1766              : 
    1767         6847 :       seq = end_ifcvt_sequence (if_info);
    1768         6847 :       if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
    1769         3937 :         return false;
    1770              : 
    1771         2910 :       emit_insn_before_setloc (seq, if_info->jump,
    1772         2910 :                                INSN_LOCATION (if_info->insn_a));
    1773         2910 :       if_info->transform_name = "noce_try_store_flag_constants";
    1774              : 
    1775         2910 :       return true;
    1776              :     }
    1777              : 
    1778              :   return false;
    1779              : }
    1780              : 
    1781              : /* Convert "if (test) foo++" into "foo += (test != 0)", and
    1782              :    similarly for "foo--".  */
    1783              : 
    1784              : static bool
    1785       181727 : noce_try_addcc (struct noce_if_info *if_info)
    1786              : {
    1787       181727 :   rtx target;
    1788       181727 :   rtx_insn *seq;
    1789       181727 :   bool subtract;
    1790       181727 :   int normalize;
    1791              : 
    1792       378438 :   if (!noce_simple_bbs (if_info))
    1793              :     return false;
    1794              : 
    1795       163741 :   if (GET_CODE (if_info->a) == PLUS
    1796        20425 :       && rtx_equal_p (XEXP (if_info->a, 0), if_info->b)
    1797       180406 :       && noce_reversed_cond_code (if_info) != UNKNOWN)
    1798              :     {
    1799        16665 :       rtx cond = if_info->rev_cond;
    1800        16665 :       enum rtx_code code;
    1801              : 
    1802        16665 :       if (cond == NULL_RTX)
    1803              :         {
    1804            0 :           cond = if_info->cond;
    1805            0 :           code = reversed_comparison_code (cond, if_info->jump);
    1806              :         }
    1807              :       else
    1808        16665 :         code = GET_CODE (cond);
    1809              : 
    1810              :       /* First try to use addcc pattern.  */
    1811        16665 :       if (general_operand (XEXP (cond, 0), VOIDmode)
    1812        16665 :           && general_operand (XEXP (cond, 1), VOIDmode))
    1813              :         {
    1814        15160 :           start_sequence ();
    1815        45480 :           target = emit_conditional_add (if_info->x, code,
    1816              :                                          XEXP (cond, 0),
    1817              :                                          XEXP (cond, 1),
    1818              :                                          VOIDmode,
    1819              :                                          if_info->b,
    1820        15160 :                                          XEXP (if_info->a, 1),
    1821        15160 :                                          GET_MODE (if_info->x),
    1822        15160 :                                          (code == LTU || code == GEU
    1823        15160 :                                           || code == LEU || code == GTU));
    1824        15160 :           if (target)
    1825              :             {
    1826         1274 :               if (target != if_info->x)
    1827            0 :                 noce_emit_move_insn (if_info->x, target);
    1828              : 
    1829         1274 :               seq = end_ifcvt_sequence (if_info);
    1830         1274 :               if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
    1831            0 :                 return false;
    1832              : 
    1833         1274 :               emit_insn_before_setloc (seq, if_info->jump,
    1834         1274 :                                        INSN_LOCATION (if_info->insn_a));
    1835         1274 :               if_info->transform_name = "noce_try_addcc";
    1836              : 
    1837         1274 :               return true;
    1838              :             }
    1839        13886 :           end_sequence ();
    1840              :         }
    1841              : 
    1842              :       /* If that fails, construct conditional increment or decrement using
    1843              :          setcc.  We're changing a branch and an increment to a comparison and
    1844              :          an ADD/SUB.  */
    1845        15391 :       if (XEXP (if_info->a, 1) == const1_rtx
    1846        10674 :           || XEXP (if_info->a, 1) == constm1_rtx)
    1847              :         {
    1848         5244 :           start_sequence ();
    1849         5244 :           if (STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1)))
    1850              :             subtract = false, normalize = 0;
    1851          527 :           else if (-STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1)))
    1852              :             subtract = true, normalize = 0;
    1853              :           else
    1854            0 :             subtract = false, normalize = INTVAL (XEXP (if_info->a, 1));
    1855              : 
    1856              : 
    1857         5244 :           target = noce_emit_store_flag (if_info,
    1858         5244 :                                          gen_reg_rtx (GET_MODE (if_info->x)),
    1859              :                                          true, normalize);
    1860              : 
    1861         5244 :           if (target)
    1862         8076 :             target = expand_simple_binop (GET_MODE (if_info->x),
    1863              :                                           subtract ? MINUS : PLUS,
    1864              :                                           if_info->b, target, if_info->x,
    1865              :                                           0, OPTAB_WIDEN);
    1866         4295 :           if (target)
    1867              :             {
    1868         4295 :               if (target != if_info->x)
    1869            0 :                 noce_emit_move_insn (if_info->x, target);
    1870              : 
    1871         4295 :               seq = end_ifcvt_sequence (if_info);
    1872         4295 :               if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
    1873          797 :                 return false;
    1874              : 
    1875         3498 :               emit_insn_before_setloc (seq, if_info->jump,
    1876         3498 :                                        INSN_LOCATION (if_info->insn_a));
    1877         3498 :               if_info->transform_name = "noce_try_addcc";
    1878         3498 :               return true;
    1879              :             }
    1880          949 :           end_sequence ();
    1881              :         }
    1882              :     }
    1883              : 
    1884              :   return false;
    1885              : }
    1886              : 
    1887              : /* Convert "if (test) x = 0;" to "x &= -(test == 0);"  */
    1888              : 
    1889              : static bool
    1890       176955 : noce_try_store_flag_mask (struct noce_if_info *if_info)
    1891              : {
    1892       176955 :   rtx target;
    1893       176955 :   rtx_insn *seq;
    1894       176955 :   bool reversep;
    1895              : 
    1896       373580 :   if (!noce_simple_bbs (if_info))
    1897              :     return false;
    1898              : 
    1899       158969 :   reversep = false;
    1900              : 
    1901       158969 :   if ((if_info->a == const0_rtx
    1902         2568 :        && (REG_P (if_info->b) || rtx_equal_p (if_info->b, if_info->x)))
    1903       160414 :       || ((reversep = (noce_reversed_cond_code (if_info) != UNKNOWN))
    1904       157846 :           && if_info->b == const0_rtx
    1905        13873 :           && (REG_P (if_info->a) || rtx_equal_p (if_info->a, if_info->x))))
    1906              :     {
    1907         1129 :       start_sequence ();
    1908         1129 :       target = noce_emit_store_flag (if_info,
    1909         1129 :                                      gen_reg_rtx (GET_MODE (if_info->x)),
    1910              :                                      reversep, -1);
    1911         1129 :       if (target)
    1912          315 :         target = expand_simple_binop (GET_MODE (if_info->x), AND,
    1913              :                                       reversep ? if_info->a : if_info->b,
    1914              :                                       target, if_info->x, 0,
    1915              :                                       OPTAB_WIDEN);
    1916              : 
    1917          315 :       if (target)
    1918              :         {
    1919          315 :           if (target != if_info->x)
    1920            0 :             noce_emit_move_insn (if_info->x, target);
    1921              : 
    1922          315 :           seq = end_ifcvt_sequence (if_info);
    1923          315 :           if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
    1924          313 :             return false;
    1925              : 
    1926            2 :           emit_insn_before_setloc (seq, if_info->jump,
    1927            2 :                                    INSN_LOCATION (if_info->insn_a));
    1928            2 :           if_info->transform_name = "noce_try_store_flag_mask";
    1929              : 
    1930            2 :           return true;
    1931              :         }
    1932              : 
    1933          814 :       end_sequence ();
    1934              :     }
    1935              : 
    1936              :   return false;
    1937              : }
    1938              : 
    1939              : /* Helper function for noce_try_cmove and noce_try_cmove_arith.  */
    1940              : 
    1941              : static rtx
    1942       483056 : noce_emit_cmove (struct noce_if_info *if_info, rtx x, enum rtx_code code,
    1943              :                  rtx cmp_a, rtx cmp_b, rtx vfalse, rtx vtrue, rtx cc_cmp,
    1944              :                  rtx rev_cc_cmp)
    1945              : {
    1946       483056 :   rtx target ATTRIBUTE_UNUSED;
    1947       483056 :   bool unsignedp ATTRIBUTE_UNUSED;
    1948              : 
    1949              :   /* If earliest == jump, try to build the cmove insn directly.
    1950              :      This is helpful when combine has created some complex condition
    1951              :      (like for alpha's cmovlbs) that we can't hope to regenerate
    1952              :      through the normal interface.  */
    1953              : 
    1954       483056 :   if (if_info->cond_earliest == if_info->jump)
    1955              :     {
    1956         4469 :       rtx cond = gen_rtx_fmt_ee (code, GET_MODE (if_info->cond), cmp_a, cmp_b);
    1957         4469 :       rtx if_then_else = gen_rtx_IF_THEN_ELSE (GET_MODE (x),
    1958              :                                                cond, vtrue, vfalse);
    1959         4469 :       rtx set = gen_rtx_SET (x, if_then_else);
    1960              : 
    1961         4469 :       start_sequence ();
    1962         4469 :       rtx_insn *insn = emit_insn (set);
    1963              : 
    1964         4469 :       if (recog_memoized (insn) >= 0)
    1965              :         {
    1966         1348 :           rtx_insn *seq = end_sequence ();
    1967         1348 :           emit_insn (seq);
    1968              : 
    1969         1348 :           return x;
    1970              :         }
    1971              : 
    1972         3121 :       end_sequence ();
    1973              :     }
    1974              : 
    1975       963416 :   unsignedp = (code == LTU || code == GEU
    1976       481708 :                || code == LEU || code == GTU);
    1977              : 
    1978       481708 :   if (cc_cmp != NULL_RTX && rev_cc_cmp != NULL_RTX)
    1979        87566 :     target = emit_conditional_move (x, cc_cmp, rev_cc_cmp,
    1980        87566 :                                     vtrue, vfalse, GET_MODE (x));
    1981              :   else
    1982              :     {
    1983              :       /* Don't even try if the comparison operands are weird
    1984              :          except that the target supports cbranchcc4.  */
    1985       394142 :       if (! general_operand (cmp_a, GET_MODE (cmp_a))
    1986       394142 :           || ! general_operand (cmp_b, GET_MODE (cmp_b)))
    1987              :         {
    1988        37705 :           if (!have_cbranchcc4
    1989        37705 :               || GET_MODE_CLASS (GET_MODE (cmp_a)) != MODE_CC
    1990         2862 :               || cmp_b != const0_rtx)
    1991              :             return NULL_RTX;
    1992              :         }
    1993              : 
    1994       359299 :       target = emit_conditional_move (x, { code, cmp_a, cmp_b, VOIDmode },
    1995       359299 :                                       vtrue, vfalse, GET_MODE (x),
    1996              :                                       unsignedp);
    1997              :     }
    1998              : 
    1999       446865 :   if (target)
    2000              :     return target;
    2001              : 
    2002              :   /* We might be faced with a situation like:
    2003              : 
    2004              :      x = (reg:M TARGET)
    2005              :      vtrue = (subreg:M (reg:N VTRUE) BYTE)
    2006              :      vfalse = (subreg:M (reg:N VFALSE) BYTE)
    2007              : 
    2008              :      We can't do a conditional move in mode M, but it's possible that we
    2009              :      could do a conditional move in mode N instead and take a subreg of
    2010              :      the result.
    2011              : 
    2012              :      If we can't create new pseudos, though, don't bother.  */
    2013        42387 :   if (reload_completed)
    2014              :     return NULL_RTX;
    2015              : 
    2016        42387 :   if (GET_CODE (vtrue) == SUBREG && GET_CODE (vfalse) == SUBREG)
    2017              :     {
    2018           23 :       rtx reg_vtrue = SUBREG_REG (vtrue);
    2019           23 :       rtx reg_vfalse = SUBREG_REG (vfalse);
    2020           23 :       poly_uint64 byte_vtrue = SUBREG_BYTE (vtrue);
    2021           23 :       poly_uint64 byte_vfalse = SUBREG_BYTE (vfalse);
    2022           23 :       rtx promoted_target;
    2023              : 
    2024           23 :       if (GET_MODE (reg_vtrue) != GET_MODE (reg_vfalse)
    2025           23 :           || maybe_ne (byte_vtrue, byte_vfalse)
    2026           23 :           || (SUBREG_PROMOTED_VAR_P (vtrue)
    2027           23 :               != SUBREG_PROMOTED_VAR_P (vfalse))
    2028           23 :           || (SUBREG_PROMOTED_GET (vtrue)
    2029           23 :               != SUBREG_PROMOTED_GET (vfalse)))
    2030              :         return NULL_RTX;
    2031              : 
    2032           23 :       promoted_target = gen_reg_rtx (GET_MODE (reg_vtrue));
    2033              : 
    2034           46 :       target = emit_conditional_move (promoted_target,
    2035              :                                       { code, cmp_a, cmp_b, VOIDmode },
    2036              :                                       reg_vtrue, reg_vfalse,
    2037           23 :                                       GET_MODE (reg_vtrue), unsignedp);
    2038              :       /* Nope, couldn't do it in that mode either.  */
    2039           23 :       if (!target)
    2040              :         return NULL_RTX;
    2041              : 
    2042            6 :       target = gen_rtx_SUBREG (GET_MODE (vtrue), promoted_target, byte_vtrue);
    2043            6 :       SUBREG_PROMOTED_VAR_P (target) = SUBREG_PROMOTED_VAR_P (vtrue);
    2044            6 :       SUBREG_PROMOTED_SET (target, SUBREG_PROMOTED_GET (vtrue));
    2045            6 :       emit_move_insn (x, target);
    2046            6 :       return x;
    2047              :     }
    2048              :   else
    2049              :     return NULL_RTX;
    2050              : }
    2051              : 
    2052              : /* Try only simple constants and registers here.  More complex cases
    2053              :    are handled in noce_try_cmove_arith after noce_try_store_flag_arith
    2054              :    has had a go at it.  */
    2055              : 
    2056              : static bool
    2057       226056 : noce_try_cmove (struct noce_if_info *if_info)
    2058              : {
    2059       226056 :   enum rtx_code code;
    2060       226056 :   rtx target;
    2061       226056 :   rtx_insn *seq;
    2062              : 
    2063       443739 :   if (!noce_simple_bbs (if_info))
    2064              :     return false;
    2065              : 
    2066       150440 :   if ((CONSTANT_P (if_info->a) || register_operand (if_info->a, VOIDmode))
    2067       243162 :       && (CONSTANT_P (if_info->b) || register_operand (if_info->b, VOIDmode)))
    2068              :     {
    2069        86348 :       start_sequence ();
    2070              : 
    2071        86348 :       code = GET_CODE (if_info->cond);
    2072        86348 :       target = noce_emit_cmove (if_info, if_info->x, code,
    2073              :                                 XEXP (if_info->cond, 0),
    2074              :                                 XEXP (if_info->cond, 1),
    2075              :                                 if_info->a, if_info->b);
    2076              : 
    2077        86348 :       if (target)
    2078              :         {
    2079        58851 :           if (target != if_info->x)
    2080            0 :             noce_emit_move_insn (if_info->x, target);
    2081              : 
    2082        58851 :           seq = end_ifcvt_sequence (if_info);
    2083        58851 :           if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
    2084        14548 :             return false;
    2085              : 
    2086        44303 :           emit_insn_before_setloc (seq, if_info->jump,
    2087        44303 :                                    INSN_LOCATION (if_info->insn_a));
    2088        44303 :           if_info->transform_name = "noce_try_cmove";
    2089              : 
    2090        44303 :           return true;
    2091              :         }
    2092              :       /* If both a and b are constants try a last-ditch transformation:
    2093              :          if (test) x = a; else x = b;
    2094              :          =>   x = (-(test != 0) & (b - a)) + a;
    2095              :          Try this only if the target-specific expansion above has failed.
    2096              :          The target-specific expander may want to generate sequences that
    2097              :          we don't know about, so give them a chance before trying this
    2098              :          approach.  */
    2099        27497 :       else if (!targetm.have_conditional_execution ()
    2100        27497 :                 && CONST_INT_P (if_info->a) && CONST_INT_P (if_info->b))
    2101              :         {
    2102         5095 :           machine_mode mode = GET_MODE (if_info->x);
    2103         5095 :           HOST_WIDE_INT ifalse = INTVAL (if_info->a);
    2104         5095 :           HOST_WIDE_INT itrue = INTVAL (if_info->b);
    2105         5095 :           rtx target = noce_emit_store_flag (if_info, if_info->x, false, -1);
    2106         5095 :           if (!target)
    2107              :             {
    2108         5013 :               end_sequence ();
    2109         5013 :               return false;
    2110              :             }
    2111              : 
    2112           82 :           HOST_WIDE_INT diff = (unsigned HOST_WIDE_INT) itrue - ifalse;
    2113              :           /* Make sure we can represent the difference
    2114              :              between the two values.  */
    2115           82 :           if ((diff > 0)
    2116           82 :               != ((ifalse < 0) != (itrue < 0) ? ifalse < 0 : ifalse < itrue))
    2117              :             {
    2118           39 :               end_sequence ();
    2119           39 :               return false;
    2120              :             }
    2121              : 
    2122           43 :           diff = trunc_int_for_mode (diff, mode);
    2123           43 :           target = expand_simple_binop (mode, AND,
    2124           43 :                                         target, gen_int_mode (diff, mode),
    2125              :                                         if_info->x, 0, OPTAB_WIDEN);
    2126           43 :           if (target)
    2127           43 :             target = expand_simple_binop (mode, PLUS,
    2128           43 :                                           target, gen_int_mode (ifalse, mode),
    2129              :                                           if_info->x, 0, OPTAB_WIDEN);
    2130           43 :           if (target)
    2131              :             {
    2132           43 :               if (target != if_info->x)
    2133            0 :                 noce_emit_move_insn (if_info->x, target);
    2134              : 
    2135           43 :               seq = end_ifcvt_sequence (if_info);
    2136           43 :               if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
    2137           17 :                 return false;
    2138              : 
    2139           26 :               emit_insn_before_setloc (seq, if_info->jump,
    2140           26 :                                    INSN_LOCATION (if_info->insn_a));
    2141           26 :               if_info->transform_name = "noce_try_cmove";
    2142           26 :               return true;
    2143              :             }
    2144              :           else
    2145              :             {
    2146            0 :               end_sequence ();
    2147            0 :               return false;
    2148              :             }
    2149              :         }
    2150              :       else
    2151        22402 :         end_sequence ();
    2152              :     }
    2153              : 
    2154              :   return false;
    2155              : }
    2156              : 
    2157              : /* Return true if X contains a conditional code mode rtx.  */
    2158              : 
    2159              : static bool
    2160      2891238 : contains_ccmode_rtx_p (rtx x)
    2161              : {
    2162      2891238 :   subrtx_iterator::array_type array;
    2163      7333064 :   FOR_EACH_SUBRTX (iter, array, x, ALL)
    2164      4483642 :     if (GET_MODE_CLASS (GET_MODE (*iter)) == MODE_CC)
    2165        41816 :       return true;
    2166              : 
    2167      2849422 :   return false;
    2168      2891238 : }
    2169              : 
    2170              : /* Helper for bb_valid_for_noce_process_p.  Validate that
    2171              :    the rtx insn INSN is a single set that does not set
    2172              :    the conditional register CC and is in general valid for
    2173              :    if-conversion.  */
    2174              : 
    2175              : static bool
    2176      3586927 : insn_valid_noce_process_p (rtx_insn *insn, rtx cc)
    2177              : {
    2178      3586927 :   if (!insn
    2179      3586704 :       || !NONJUMP_INSN_P (insn)
    2180      6505514 :       || (cc && set_of (cc, insn)))
    2181       676270 :       return false;
    2182              : 
    2183      2910657 :   rtx sset = single_set (insn);
    2184              : 
    2185              :   /* Currently support only simple single sets in test_bb.  */
    2186      2910657 :   if (!sset
    2187      2904534 :       || !noce_operand_ok (SET_DEST (sset))
    2188      2891238 :       || contains_ccmode_rtx_p (SET_DEST (sset))
    2189      5760079 :       || !noce_operand_ok (SET_SRC (sset)))
    2190       122370 :     return false;
    2191              : 
    2192              :   return true;
    2193              : }
    2194              : 
    2195              : 
    2196              : /* Return true iff the registers that the insns in BB_A set do not get
    2197              :    used in BB_B.  If TO_RENAME is non-NULL then it is a location that will be
    2198              :    renamed later by the caller and so conflicts on it should be ignored
    2199              :    in this function.  */
    2200              : 
    2201              : static bool
    2202        52148 : bbs_ok_for_cmove_arith (basic_block bb_a, basic_block bb_b, rtx to_rename)
    2203              : {
    2204        52148 :   rtx_insn *a_insn;
    2205        52148 :   bitmap bba_sets = BITMAP_ALLOC (&reg_obstack);
    2206              : 
    2207        52148 :   df_ref def;
    2208        52148 :   df_ref use;
    2209              : 
    2210       269809 :   FOR_BB_INSNS (bb_a, a_insn)
    2211              :     {
    2212       217661 :       if (!active_insn_p (a_insn))
    2213       146321 :         continue;
    2214              : 
    2215        71340 :       rtx sset_a = single_set (a_insn);
    2216              : 
    2217        71340 :       if (!sset_a)
    2218              :         {
    2219            0 :           BITMAP_FREE (bba_sets);
    2220            0 :           return false;
    2221              :         }
    2222              :       /* Record all registers that BB_A sets.  */
    2223       172642 :       FOR_EACH_INSN_DEF (def, a_insn)
    2224       101302 :         if (!(to_rename && DF_REF_REG (def) == to_rename))
    2225        49892 :           bitmap_set_bit (bba_sets, DF_REF_REGNO (def));
    2226              :     }
    2227              : 
    2228        52148 :   rtx_insn *b_insn;
    2229              : 
    2230       269871 :   FOR_BB_INSNS (bb_b, b_insn)
    2231              :     {
    2232       217817 :       if (!active_insn_p (b_insn))
    2233       146484 :         continue;
    2234              : 
    2235        71333 :       rtx sset_b = single_set (b_insn);
    2236              : 
    2237        71333 :       if (!sset_b)
    2238              :         {
    2239            0 :           BITMAP_FREE (bba_sets);
    2240            0 :           return false;
    2241              :         }
    2242              : 
    2243              :       /* Make sure this is a REG and not some instance
    2244              :          of ZERO_EXTRACT or non-paradoxical SUBREG or other dangerous stuff.
    2245              :          If we have a memory destination then we have a pair of simple
    2246              :          basic blocks performing an operation of the form [addr] = c ? a : b.
    2247              :          bb_valid_for_noce_process_p will have ensured that these are
    2248              :          the only stores present.  In that case [addr] should be the location
    2249              :          to be renamed.  Assert that the callers set this up properly.  */
    2250        71333 :       if (MEM_P (SET_DEST (sset_b)))
    2251          730 :         gcc_assert (rtx_equal_p (SET_DEST (sset_b), to_rename));
    2252        70603 :       else if (!REG_P (SET_DEST (sset_b))
    2253        70603 :                && !paradoxical_subreg_p (SET_DEST (sset_b)))
    2254              :         {
    2255           37 :           BITMAP_FREE (bba_sets);
    2256           37 :           return false;
    2257              :         }
    2258              : 
    2259              :       /* If the insn uses a reg set in BB_A return false.  */
    2260       137596 :       FOR_EACH_INSN_USE (use, b_insn)
    2261              :         {
    2262        66357 :           if (bitmap_bit_p (bba_sets, DF_REF_REGNO (use)))
    2263              :             {
    2264           57 :               BITMAP_FREE (bba_sets);
    2265           57 :               return false;
    2266              :             }
    2267              :         }
    2268              : 
    2269              :     }
    2270              : 
    2271        52054 :   BITMAP_FREE (bba_sets);
    2272        52054 :   return true;
    2273              : }
    2274              : 
    2275              : /* Emit copies of all the active instructions in BB except the last.
    2276              :    This is a helper for noce_try_cmove_arith.  */
    2277              : 
    2278              : static void
    2279        13408 : noce_emit_all_but_last (basic_block bb)
    2280              : {
    2281        13408 :   rtx_insn *last = last_active_insn (bb, false);
    2282        13408 :   rtx_insn *insn;
    2283       141193 :   FOR_BB_INSNS (bb, insn)
    2284              :     {
    2285       114377 :       if (insn != last && active_insn_p (insn))
    2286              :         {
    2287        35234 :           rtx_insn *to_emit = as_a <rtx_insn *> (copy_rtx (insn));
    2288              : 
    2289        35234 :           emit_insn (PATTERN (to_emit));
    2290              :         }
    2291              :     }
    2292        13408 : }
    2293              : 
    2294              : /* Helper for noce_try_cmove_arith.  Emit the pattern TO_EMIT and return
    2295              :    the resulting insn or NULL if it's not a valid insn.  */
    2296              : 
    2297              : static rtx_insn *
    2298       194065 : noce_emit_insn (rtx to_emit)
    2299              : {
    2300       194065 :   gcc_assert (to_emit);
    2301       194065 :   rtx_insn *insn = emit_insn (to_emit);
    2302              : 
    2303       194065 :   if (recog_memoized (insn) < 0)
    2304          200 :     return NULL;
    2305              : 
    2306              :   return insn;
    2307              : }
    2308              : 
    2309              : /* Helper for noce_try_cmove_arith.  Emit a copy of the insns up to
    2310              :    and including the penultimate one in BB if it is not simple
    2311              :    (as indicated by SIMPLE).  Then emit LAST_INSN as the last
    2312              :    insn in the block.  The reason for that is that LAST_INSN may
    2313              :    have been modified by the preparation in noce_try_cmove_arith.  */
    2314              : 
    2315              : static bool
    2316       196023 : noce_emit_bb (rtx last_insn, basic_block bb, bool simple)
    2317              : {
    2318       196023 :   if (bb && !simple)
    2319        13408 :     noce_emit_all_but_last (bb);
    2320              : 
    2321       196023 :   if (last_insn && !noce_emit_insn (last_insn))
    2322              :     return false;
    2323              : 
    2324              :   return true;
    2325              : }
    2326              : 
    2327              : /* Try more complex cases involving conditional_move.  */
    2328              : 
    2329              : static bool
    2330       168529 : noce_try_cmove_arith (struct noce_if_info *if_info)
    2331              : {
    2332       168529 :   rtx a = if_info->a;
    2333       168529 :   rtx b = if_info->b;
    2334       168529 :   rtx x = if_info->x;
    2335       168529 :   rtx orig_a, orig_b;
    2336       168529 :   rtx_insn *insn_a, *insn_b;
    2337       168529 :   bool a_simple = if_info->then_simple;
    2338       168529 :   bool b_simple = if_info->else_simple;
    2339       168529 :   basic_block then_bb = if_info->then_bb;
    2340       168529 :   basic_block else_bb = if_info->else_bb;
    2341       168529 :   rtx target;
    2342       168529 :   bool is_mem = false;
    2343       168529 :   enum rtx_code code;
    2344       168529 :   rtx cond = if_info->cond;
    2345       168529 :   rtx_insn *ifcvt_seq;
    2346              : 
    2347              :   /* A conditional move from two memory sources is equivalent to a
    2348              :      conditional on their addresses followed by a load.  Don't do this
    2349              :      early because it'll screw alias analysis.  Note that we've
    2350              :      already checked for no side effects.  */
    2351       168529 :   if (cse_not_expected
    2352        58951 :       && MEM_P (a) && MEM_P (b)
    2353       173096 :       && MEM_ADDR_SPACE (a) == MEM_ADDR_SPACE (b))
    2354              :     {
    2355         4567 :       machine_mode address_mode = get_address_mode (a);
    2356              : 
    2357         4567 :       a = XEXP (a, 0);
    2358         4567 :       b = XEXP (b, 0);
    2359         4567 :       x = gen_reg_rtx (address_mode);
    2360         4567 :       is_mem = true;
    2361              :     }
    2362              : 
    2363              :   /* ??? We could handle this if we knew that a load from A or B could
    2364              :      not trap or fault.  This is also true if we've already loaded
    2365              :      from the address along the path from ENTRY.  */
    2366       163962 :   else if (may_trap_or_fault_p (a) || may_trap_or_fault_p (b))
    2367        50625 :     return false;
    2368              : 
    2369              :   /* if (test) x = a + b; else x = c - d;
    2370              :      => y = a + b;
    2371              :         x = c - d;
    2372              :         if (test)
    2373              :           x = y;
    2374              :   */
    2375              : 
    2376       117904 :   code = GET_CODE (cond);
    2377       117904 :   insn_a = if_info->insn_a;
    2378       117904 :   insn_b = if_info->insn_b;
    2379              : 
    2380       117904 :   machine_mode x_mode = GET_MODE (x);
    2381              : 
    2382       117904 :   if (!can_conditionally_move_p (x_mode))
    2383              :     return false;
    2384              : 
    2385              :   /* Possibly rearrange operands to make things come out more natural.  */
    2386        98110 :   if (noce_reversed_cond_code (if_info) != UNKNOWN)
    2387              :     {
    2388        98110 :       bool reversep = false;
    2389        98110 :       if (rtx_equal_p (b, x))
    2390              :         reversep = true;
    2391        54950 :       else if (general_operand (b, GET_MODE (b)))
    2392              :         reversep = true;
    2393              : 
    2394              :       if (reversep)
    2395              :         {
    2396        89914 :           if (if_info->rev_cond)
    2397              :             {
    2398        89914 :               cond = if_info->rev_cond;
    2399        89914 :               code = GET_CODE (cond);
    2400              :             }
    2401              :           else
    2402            0 :             code = reversed_comparison_code (cond, if_info->jump);
    2403              :           std::swap (a, b);
    2404              :           std::swap (insn_a, insn_b);
    2405              :           std::swap (a_simple, b_simple);
    2406              :           std::swap (then_bb, else_bb);
    2407              :         }
    2408              :     }
    2409              : 
    2410        26950 :   if (then_bb && else_bb
    2411       124231 :       && (!bbs_ok_for_cmove_arith (then_bb, else_bb,  if_info->orig_x)
    2412        26027 :           || !bbs_ok_for_cmove_arith (else_bb, then_bb,  if_info->orig_x)))
    2413           94 :     return false;
    2414              : 
    2415        98016 :   start_sequence ();
    2416              : 
    2417              :   /* If one of the blocks is empty then the corresponding B or A value
    2418              :      came from the test block.  The non-empty complex block that we will
    2419              :      emit might clobber the register used by B or A, so move it to a pseudo
    2420              :      first.  */
    2421              : 
    2422        98016 :   rtx tmp_a = NULL_RTX;
    2423        98016 :   rtx tmp_b = NULL_RTX;
    2424              : 
    2425        98016 :   if (b_simple || !else_bb)
    2426        86600 :     tmp_b = gen_reg_rtx (x_mode);
    2427              : 
    2428        98016 :   if (a_simple || !then_bb)
    2429        96024 :     tmp_a = gen_reg_rtx (x_mode);
    2430              : 
    2431        98016 :   orig_a = a;
    2432        98016 :   orig_b = b;
    2433              : 
    2434        98016 :   rtx emit_a = NULL_RTX;
    2435        98016 :   rtx emit_b = NULL_RTX;
    2436        98016 :   rtx_insn *tmp_insn = NULL;
    2437        98016 :   bool modified_in_a = false;
    2438        98016 :   bool modified_in_b = false;
    2439              :   /* If either operand is complex, load it into a register first.
    2440              :      The best way to do this is to copy the original insn.  In this
    2441              :      way we preserve any clobbers etc that the insn may have had.
    2442              :      This is of course not possible in the IS_MEM case.  */
    2443              : 
    2444        98016 :   if (! general_operand (a, GET_MODE (a)) || tmp_a)
    2445              :     {
    2446              : 
    2447        97529 :       if (is_mem)
    2448              :         {
    2449         4566 :           rtx reg = gen_reg_rtx (GET_MODE (a));
    2450         4566 :           emit_a = gen_rtx_SET (reg, a);
    2451              :         }
    2452              :       else
    2453              :         {
    2454        92963 :           if (insn_a)
    2455              :             {
    2456        49744 :               a = tmp_a ? tmp_a : gen_reg_rtx (GET_MODE (a));
    2457              : 
    2458        49744 :               rtx_insn *copy_of_a = as_a <rtx_insn *> (copy_rtx (insn_a));
    2459        49744 :               rtx set = single_set (copy_of_a);
    2460        49744 :               SET_DEST (set) = a;
    2461              : 
    2462        49744 :               emit_a = PATTERN (copy_of_a);
    2463              :             }
    2464              :           else
    2465              :             {
    2466        43219 :               rtx tmp_reg = tmp_a ? tmp_a : gen_reg_rtx (GET_MODE (a));
    2467        43219 :               emit_a = gen_rtx_SET (tmp_reg, a);
    2468        43219 :               a = tmp_reg;
    2469              :             }
    2470              :         }
    2471              :     }
    2472              : 
    2473        98016 :   if (! general_operand (b, GET_MODE (b)) || tmp_b)
    2474              :     {
    2475        96545 :       if (is_mem)
    2476              :         {
    2477         4566 :           rtx reg = gen_reg_rtx (GET_MODE (b));
    2478         4566 :           emit_b = gen_rtx_SET (reg, b);
    2479              :         }
    2480              :       else
    2481              :         {
    2482        91979 :           if (insn_b)
    2483              :             {
    2484        91789 :               b = tmp_b ? tmp_b : gen_reg_rtx (GET_MODE (b));
    2485        91789 :               rtx_insn *copy_of_b = as_a <rtx_insn *> (copy_rtx (insn_b));
    2486        91789 :               rtx set = single_set (copy_of_b);
    2487              : 
    2488        91789 :               SET_DEST (set) = b;
    2489        91789 :               emit_b = PATTERN (copy_of_b);
    2490              :             }
    2491              :           else
    2492              :             {
    2493          190 :               rtx tmp_reg = tmp_b ? tmp_b : gen_reg_rtx (GET_MODE (b));
    2494          190 :               emit_b = gen_rtx_SET (tmp_reg, b);
    2495          190 :               b = tmp_reg;
    2496              :             }
    2497              :         }
    2498              :     }
    2499              : 
    2500        98016 :   modified_in_a = emit_a != NULL_RTX && modified_in_p (orig_b, emit_a);
    2501        98016 :   if (tmp_b && then_bb)
    2502              :     {
    2503        74807 :       FOR_BB_INSNS (then_bb, tmp_insn)
    2504              :         /* Don't check inside insn_a.  We will have changed it to emit_a
    2505              :            with a destination that doesn't conflict.  */
    2506        56350 :         if (!(insn_a && tmp_insn == insn_a)
    2507        94243 :             && modified_in_p (orig_b, tmp_insn))
    2508              :           {
    2509              :             modified_in_a = true;
    2510              :             break;
    2511              :           }
    2512              : 
    2513              :     }
    2514              : 
    2515        98016 :   modified_in_b = emit_b != NULL_RTX && modified_in_p (orig_a, emit_b);
    2516        98016 :   if (tmp_a && else_bb)
    2517              :     {
    2518       407221 :       FOR_BB_INSNS (else_bb, tmp_insn)
    2519              :       /* Don't check inside insn_b.  We will have changed it to emit_b
    2520              :          with a destination that doesn't conflict.  */
    2521       311983 :       if (!(insn_b && tmp_insn == insn_b)
    2522       528728 :           && modified_in_p (orig_a, tmp_insn))
    2523              :         {
    2524              :           modified_in_b = true;
    2525              :           break;
    2526              :         }
    2527              :     }
    2528              : 
    2529              :   /* If insn to set up A clobbers any registers B depends on, try to
    2530              :      swap insn that sets up A with the one that sets up B.  If even
    2531              :      that doesn't help, punt.  */
    2532        98016 :   if (modified_in_a && !modified_in_b)
    2533              :     {
    2534            0 :       if (!noce_emit_bb (emit_b, else_bb, b_simple))
    2535            0 :         goto end_seq_and_fail;
    2536              : 
    2537            0 :       if (!noce_emit_bb (emit_a, then_bb, a_simple))
    2538            0 :         goto end_seq_and_fail;
    2539              :     }
    2540        98016 :   else if (!modified_in_a)
    2541              :     {
    2542        98016 :       if (!noce_emit_bb (emit_a, then_bb, a_simple))
    2543            9 :         goto end_seq_and_fail;
    2544              : 
    2545        98007 :       if (!noce_emit_bb (emit_b, else_bb, b_simple))
    2546          191 :         goto end_seq_and_fail;
    2547              :     }
    2548              :   else
    2549            0 :     goto end_seq_and_fail;
    2550              : 
    2551        97816 :   target = noce_emit_cmove (if_info, x, code, XEXP (cond, 0), XEXP (cond, 1),
    2552              :                             a, b);
    2553              : 
    2554        97816 :   if (! target)
    2555        28308 :     goto end_seq_and_fail;
    2556              : 
    2557              :   /* If we're handling a memory for above, emit the load now.  */
    2558        69508 :   if (is_mem)
    2559              :     {
    2560         2478 :       rtx mem = gen_rtx_MEM (GET_MODE (if_info->x), target);
    2561              : 
    2562              :       /* Copy over flags as appropriate.  */
    2563         2478 :       if (MEM_VOLATILE_P (if_info->a) || MEM_VOLATILE_P (if_info->b))
    2564            0 :         MEM_VOLATILE_P (mem) = 1;
    2565         2478 :       if (MEM_ALIAS_SET (if_info->a) == MEM_ALIAS_SET (if_info->b))
    2566         2296 :         set_mem_alias_set (mem, MEM_ALIAS_SET (if_info->a));
    2567         4956 :       set_mem_align (mem,
    2568         2478 :                      MIN (MEM_ALIGN (if_info->a), MEM_ALIGN (if_info->b)));
    2569              : 
    2570         2478 :       gcc_assert (MEM_ADDR_SPACE (if_info->a) == MEM_ADDR_SPACE (if_info->b));
    2571         2478 :       set_mem_addr_space (mem, MEM_ADDR_SPACE (if_info->a));
    2572              : 
    2573         2478 :       noce_emit_move_insn (if_info->x, mem);
    2574              :     }
    2575        67030 :   else if (target != x)
    2576            0 :     noce_emit_move_insn (x, target);
    2577              : 
    2578        69508 :   ifcvt_seq = end_ifcvt_sequence (if_info);
    2579        69508 :   if (!ifcvt_seq || !targetm.noce_conversion_profitable_p (ifcvt_seq, if_info))
    2580        43793 :     return false;
    2581              : 
    2582        25715 :   emit_insn_before_setloc (ifcvt_seq, if_info->jump,
    2583        25715 :                            INSN_LOCATION (if_info->insn_a));
    2584        25715 :   if_info->transform_name = "noce_try_cmove_arith";
    2585        25715 :   return true;
    2586              : 
    2587        28508 :  end_seq_and_fail:
    2588        28508 :   end_sequence ();
    2589        28508 :   return false;
    2590              : }
    2591              : 
    2592              : /* For most cases, the simplified condition we found is the best
    2593              :    choice, but this is not the case for the min/max/abs transforms.
    2594              :    For these we wish to know that it is A or B in the condition.  */
    2595              : 
    2596              : static rtx
    2597       154822 : noce_get_alt_condition (struct noce_if_info *if_info, rtx target,
    2598              :                         rtx_insn **earliest)
    2599              : {
    2600       154822 :   rtx cond, set;
    2601       154822 :   rtx_insn *insn;
    2602       154822 :   bool reverse;
    2603              : 
    2604              :   /* If target is already mentioned in the known condition, return it.  */
    2605       154822 :   if (reg_mentioned_p (target, if_info->cond))
    2606              :     {
    2607         7592 :       *earliest = if_info->cond_earliest;
    2608         7592 :       return if_info->cond;
    2609              :     }
    2610              : 
    2611       147230 :   set = pc_set (if_info->jump);
    2612       147230 :   cond = XEXP (SET_SRC (set), 0);
    2613       147230 :   reverse
    2614       294460 :     = GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
    2615       147230 :       && label_ref_label (XEXP (SET_SRC (set), 2)) == JUMP_LABEL (if_info->jump);
    2616       147230 :   if (if_info->then_else_reversed)
    2617        23157 :     reverse = !reverse;
    2618              : 
    2619              :   /* If we're looking for a constant, try to make the conditional
    2620              :      have that constant in it.  There are two reasons why it may
    2621              :      not have the constant we want:
    2622              : 
    2623              :      1. GCC may have needed to put the constant in a register, because
    2624              :         the target can't compare directly against that constant.  For
    2625              :         this case, we look for a SET immediately before the comparison
    2626              :         that puts a constant in that register.
    2627              : 
    2628              :      2. GCC may have canonicalized the conditional, for example
    2629              :         replacing "if x < 4" with "if x <= 3".  We can undo that (or
    2630              :         make equivalent types of changes) to get the constants we need
    2631              :         if they're off by one in the right direction.  */
    2632              : 
    2633       147230 :   if (CONST_INT_P (target))
    2634              :     {
    2635        44723 :       enum rtx_code code = GET_CODE (if_info->cond);
    2636        44723 :       rtx op_a = XEXP (if_info->cond, 0);
    2637        44723 :       rtx op_b = XEXP (if_info->cond, 1);
    2638        44723 :       rtx_insn *prev_insn;
    2639              : 
    2640              :       /* First, look to see if we put a constant in a register.  */
    2641        44723 :       prev_insn = prev_nonnote_nondebug_insn (if_info->cond_earliest);
    2642        44723 :       if (prev_insn
    2643        44614 :           && BLOCK_FOR_INSN (prev_insn)
    2644        44614 :              == BLOCK_FOR_INSN (if_info->cond_earliest)
    2645        35741 :           && INSN_P (prev_insn)
    2646        76802 :           && GET_CODE (PATTERN (prev_insn)) == SET)
    2647              :         {
    2648        24092 :           rtx src = find_reg_equal_equiv_note (prev_insn);
    2649        24092 :           if (!src)
    2650        23926 :             src = SET_SRC (PATTERN (prev_insn));
    2651        24092 :           if (CONST_INT_P (src))
    2652              :             {
    2653        14583 :               if (rtx_equal_p (op_a, SET_DEST (PATTERN (prev_insn))))
    2654              :                 op_a = src;
    2655        14336 :               else if (rtx_equal_p (op_b, SET_DEST (PATTERN (prev_insn))))
    2656         1074 :                 op_b = src;
    2657              : 
    2658        14583 :               if (CONST_INT_P (op_a))
    2659              :                 {
    2660          247 :                   std::swap (op_a, op_b);
    2661          247 :                   code = swap_condition (code);
    2662              :                 }
    2663              :             }
    2664              :         }
    2665              : 
    2666              :       /* Now, look to see if we can get the right constant by
    2667              :          adjusting the conditional.  */
    2668        44723 :       if (CONST_INT_P (op_b))
    2669              :         {
    2670        22871 :           HOST_WIDE_INT desired_val = INTVAL (target);
    2671        22871 :           HOST_WIDE_INT actual_val = INTVAL (op_b);
    2672              : 
    2673        22871 :           switch (code)
    2674              :             {
    2675          966 :             case LT:
    2676          966 :               if (desired_val != HOST_WIDE_INT_MAX
    2677          949 :                   && actual_val == desired_val + 1)
    2678              :                 {
    2679          166 :                   code = LE;
    2680          166 :                   op_b = GEN_INT (desired_val);
    2681              :                 }
    2682              :               break;
    2683            3 :             case LE:
    2684            3 :               if (desired_val != HOST_WIDE_INT_MIN
    2685            3 :                   && actual_val == desired_val - 1)
    2686              :                 {
    2687            0 :                   code = LT;
    2688            0 :                   op_b = GEN_INT (desired_val);
    2689              :                 }
    2690              :               break;
    2691         1617 :             case GT:
    2692         1617 :               if (desired_val != HOST_WIDE_INT_MIN
    2693         1617 :                   && actual_val == desired_val - 1)
    2694              :                 {
    2695          246 :                   code = GE;
    2696          246 :                   op_b = GEN_INT (desired_val);
    2697              :                 }
    2698              :               break;
    2699           40 :             case GE:
    2700           40 :               if (desired_val != HOST_WIDE_INT_MAX
    2701           25 :                   && actual_val == desired_val + 1)
    2702              :                 {
    2703            3 :                   code = GT;
    2704            3 :                   op_b = GEN_INT (desired_val);
    2705              :                 }
    2706              :               break;
    2707              :             default:
    2708              :               break;
    2709              :             }
    2710              :         }
    2711              : 
    2712              :       /* If we made any changes, generate a new conditional that is
    2713              :          equivalent to what we started with, but has the right
    2714              :          constants in it.  */
    2715        44723 :       if (code != GET_CODE (if_info->cond)
    2716        44062 :           || op_a != XEXP (if_info->cond, 0)
    2717        44061 :           || op_b != XEXP (if_info->cond, 1))
    2718              :         {
    2719         1736 :           cond = gen_rtx_fmt_ee (code, GET_MODE (cond), op_a, op_b);
    2720         1736 :           *earliest = if_info->cond_earliest;
    2721         1736 :           return cond;
    2722              :         }
    2723              :     }
    2724              : 
    2725       145494 :   cond = canonicalize_condition (if_info->jump, cond, reverse,
    2726              :                                  earliest, target, have_cbranchcc4, true);
    2727       145494 :   if (! cond || ! reg_mentioned_p (target, cond))
    2728       145494 :     return NULL;
    2729              : 
    2730              :   /* We almost certainly searched back to a different place.
    2731              :      Need to re-verify correct lifetimes.  */
    2732              : 
    2733              :   /* X may not be mentioned in the range (cond_earliest, jump].  */
    2734            0 :   for (insn = if_info->jump; insn != *earliest; insn = PREV_INSN (insn))
    2735            0 :     if (INSN_P (insn) && reg_overlap_mentioned_p (if_info->x, PATTERN (insn)))
    2736              :       return NULL;
    2737              : 
    2738              :   /* A and B may not be modified in the range [cond_earliest, jump).  */
    2739            0 :   for (insn = *earliest; insn != if_info->jump; insn = NEXT_INSN (insn))
    2740            0 :     if (INSN_P (insn)
    2741            0 :         && (modified_in_p (if_info->a, insn)
    2742            0 :             || modified_in_p (if_info->b, insn)))
    2743            0 :       return NULL;
    2744              : 
    2745              :   return cond;
    2746              : }
    2747              : 
    2748              : /* Convert "if (a < b) x = a; else x = b;" to "x = min(a, b);", etc.  */
    2749              : 
    2750              : static bool
    2751       229231 : noce_try_minmax (struct noce_if_info *if_info)
    2752              : {
    2753       229231 :   rtx cond, target;
    2754       229231 :   rtx_insn *earliest, *seq;
    2755       229231 :   enum rtx_code code, op;
    2756       229231 :   bool unsignedp;
    2757              : 
    2758       497427 :   if (!noce_simple_bbs (if_info))
    2759              :     return false;
    2760              : 
    2761              :   /* ??? Reject modes with NaNs or signed zeros since we don't know how
    2762              :      they will be resolved with an SMIN/SMAX.  It wouldn't be too hard
    2763              :      to get the target to tell us...  */
    2764       211245 :   if (HONOR_SIGNED_ZEROS (if_info->x)
    2765       211245 :       || HONOR_NANS (if_info->x))
    2766        57448 :     return false;
    2767              : 
    2768       153797 :   cond = noce_get_alt_condition (if_info, if_info->a, &earliest);
    2769       153797 :   if (!cond)
    2770              :     return false;
    2771              : 
    2772              :   /* Verify the condition is of the form we expect, and canonicalize
    2773              :      the comparison code.  */
    2774         9298 :   code = GET_CODE (cond);
    2775         9298 :   if (rtx_equal_p (XEXP (cond, 0), if_info->a))
    2776              :     {
    2777         2365 :       if (! rtx_equal_p (XEXP (cond, 1), if_info->b))
    2778              :         return false;
    2779              :     }
    2780         6933 :   else if (rtx_equal_p (XEXP (cond, 1), if_info->a))
    2781              :     {
    2782         4279 :       if (! rtx_equal_p (XEXP (cond, 0), if_info->b))
    2783              :         return false;
    2784           39 :       code = swap_condition (code);
    2785              :     }
    2786              :   else
    2787              :     return false;
    2788              : 
    2789              :   /* Determine what sort of operation this is.  Note that the code is for
    2790              :      a taken branch, so the code->operation mapping appears backwards.  */
    2791           53 :   switch (code)
    2792              :     {
    2793              :     case LT:
    2794              :     case LE:
    2795              :     case UNLT:
    2796              :     case UNLE:
    2797              :       op = SMAX;
    2798              :       unsignedp = false;
    2799              :       break;
    2800            8 :     case GT:
    2801            8 :     case GE:
    2802            8 :     case UNGT:
    2803            8 :     case UNGE:
    2804            8 :       op = SMIN;
    2805            8 :       unsignedp = false;
    2806            8 :       break;
    2807            3 :     case LTU:
    2808            3 :     case LEU:
    2809            3 :       op = UMAX;
    2810            3 :       unsignedp = true;
    2811            3 :       break;
    2812           21 :     case GTU:
    2813           21 :     case GEU:
    2814           21 :       op = UMIN;
    2815           21 :       unsignedp = true;
    2816           21 :       break;
    2817              :     default:
    2818              :       return false;
    2819              :     }
    2820              : 
    2821           53 :   start_sequence ();
    2822              : 
    2823           53 :   target = expand_simple_binop (GET_MODE (if_info->x), op,
    2824              :                                 if_info->a, if_info->b,
    2825              :                                 if_info->x, unsignedp, OPTAB_WIDEN);
    2826           53 :   if (! target)
    2827              :     {
    2828            0 :       end_sequence ();
    2829            0 :       return false;
    2830              :     }
    2831           53 :   if (target != if_info->x)
    2832            0 :     noce_emit_move_insn (if_info->x, target);
    2833              : 
    2834           53 :   seq = end_ifcvt_sequence (if_info);
    2835           53 :   if (!seq)
    2836              :     return false;
    2837              : 
    2838           53 :   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
    2839           53 :   if_info->cond = cond;
    2840           53 :   if_info->cond_earliest = earliest;
    2841           53 :   if_info->rev_cond = NULL_RTX;
    2842           53 :   if_info->transform_name = "noce_try_minmax";
    2843              : 
    2844           53 :   return true;
    2845              : }
    2846              : 
    2847              : /* Convert "if (a < 0) x = -a; else x = a;" to "x = abs(a);",
    2848              :    "if (a < 0) x = ~a; else x = a;" to "x = one_cmpl_abs(a);",
    2849              :    etc.  */
    2850              : 
    2851              : static bool
    2852       229178 : noce_try_abs (struct noce_if_info *if_info)
    2853              : {
    2854       229178 :   rtx cond, target, a, b, c;
    2855       229178 :   rtx_insn *earliest, *seq;
    2856       229178 :   bool negate;
    2857       229178 :   bool one_cmpl = false;
    2858              : 
    2859       497339 :   if (!noce_simple_bbs (if_info))
    2860              :     return false;
    2861              : 
    2862              :   /* Reject modes with signed zeros.  */
    2863       211192 :   if (HONOR_SIGNED_ZEROS (if_info->x))
    2864              :     return false;
    2865              : 
    2866              :   /* Recognize A and B as constituting an ABS or NABS.  The canonical
    2867              :      form is a branch around the negation, taken when the object is the
    2868              :      first operand of a comparison against 0 that evaluates to true.  */
    2869       153753 :   a = if_info->a;
    2870       153753 :   b = if_info->b;
    2871       153753 :   if (GET_CODE (a) == NEG && rtx_equal_p (XEXP (a, 0), b))
    2872              :     negate = false;
    2873       152758 :   else if (GET_CODE (b) == NEG && rtx_equal_p (XEXP (b, 0), a))
    2874              :     {
    2875              :       std::swap (a, b);
    2876              :       negate = true;
    2877              :     }
    2878       152728 :   else if (GET_CODE (a) == NOT && rtx_equal_p (XEXP (a, 0), b))
    2879              :     {
    2880              :       negate = false;
    2881              :       one_cmpl = true;
    2882              :     }
    2883       152728 :   else if (GET_CODE (b) == NOT && rtx_equal_p (XEXP (b, 0), a))
    2884              :     {
    2885              :       std::swap (a, b);
    2886              :       negate = true;
    2887              :       one_cmpl = true;
    2888              :     }
    2889              :   else
    2890       152728 :     return false;
    2891              : 
    2892         1025 :   cond = noce_get_alt_condition (if_info, b, &earliest);
    2893         1025 :   if (!cond)
    2894              :     return false;
    2895              : 
    2896              :   /* Verify the condition is of the form we expect.  */
    2897           30 :   if (rtx_equal_p (XEXP (cond, 0), b))
    2898           30 :     c = XEXP (cond, 1);
    2899            0 :   else if (rtx_equal_p (XEXP (cond, 1), b))
    2900              :     {
    2901            0 :       c = XEXP (cond, 0);
    2902            0 :       negate = !negate;
    2903              :     }
    2904              :   else
    2905              :     return false;
    2906              : 
    2907              :   /* Verify that C is zero.  Search one step backward for a
    2908              :      REG_EQUAL note or a simple source if necessary.  */
    2909           30 :   if (REG_P (c))
    2910              :     {
    2911            0 :       rtx set;
    2912            0 :       rtx_insn *insn = prev_nonnote_nondebug_insn (earliest);
    2913            0 :       if (insn
    2914            0 :           && BLOCK_FOR_INSN (insn) == BLOCK_FOR_INSN (earliest)
    2915            0 :           && (set = single_set (insn))
    2916            0 :           && rtx_equal_p (SET_DEST (set), c))
    2917              :         {
    2918            0 :           rtx note = find_reg_equal_equiv_note (insn);
    2919            0 :           if (note)
    2920            0 :             c = XEXP (note, 0);
    2921              :           else
    2922            0 :             c = SET_SRC (set);
    2923              :         }
    2924              :       else
    2925            0 :         return false;
    2926              :     }
    2927           30 :   if (MEM_P (c)
    2928            0 :       && GET_CODE (XEXP (c, 0)) == SYMBOL_REF
    2929           30 :       && CONSTANT_POOL_ADDRESS_P (XEXP (c, 0)))
    2930            0 :     c = get_pool_constant (XEXP (c, 0));
    2931              : 
    2932              :   /* Work around funny ideas get_condition has wrt canonicalization.
    2933              :      Note that these rtx constants are known to be CONST_INT, and
    2934              :      therefore imply integer comparisons.
    2935              :      The one_cmpl case is more complicated, as we want to handle
    2936              :      only x < 0 ? ~x : x or x >= 0 ? x : ~x to one_cmpl_abs (x)
    2937              :      and x < 0 ? x : ~x or x >= 0 ? ~x : x to ~one_cmpl_abs (x),
    2938              :      but not other cases (x > -1 is equivalent of x >= 0).  */
    2939           30 :   if (c == constm1_rtx && GET_CODE (cond) == GT)
    2940              :     ;
    2941            6 :   else if (c == const1_rtx && GET_CODE (cond) == LT)
    2942              :     {
    2943            0 :       if (one_cmpl)
    2944              :         return false;
    2945              :     }
    2946            6 :   else if (c == CONST0_RTX (GET_MODE (b)))
    2947              :     {
    2948            0 :       if (one_cmpl
    2949            0 :           && GET_CODE (cond) != GE
    2950            0 :           && GET_CODE (cond) != LT)
    2951              :         return false;
    2952              :     }
    2953              :   else
    2954              :     return false;
    2955              : 
    2956              :   /* Determine what sort of operation this is.  */
    2957           24 :   switch (GET_CODE (cond))
    2958              :     {
    2959            0 :     case LT:
    2960            0 :     case LE:
    2961            0 :     case UNLT:
    2962            0 :     case UNLE:
    2963            0 :       negate = !negate;
    2964            0 :       break;
    2965              :     case GT:
    2966              :     case GE:
    2967              :     case UNGT:
    2968              :     case UNGE:
    2969              :       break;
    2970              :     default:
    2971              :       return false;
    2972              :     }
    2973              : 
    2974           24 :   start_sequence ();
    2975           24 :   if (one_cmpl)
    2976            0 :     target = expand_one_cmpl_abs_nojump (GET_MODE (if_info->x), b,
    2977              :                                          if_info->x);
    2978              :   else
    2979           24 :     target = expand_abs_nojump (GET_MODE (if_info->x), b, if_info->x, 1);
    2980              : 
    2981              :   /* ??? It's a quandary whether cmove would be better here, especially
    2982              :      for integers.  Perhaps combine will clean things up.  */
    2983           24 :   if (target && negate)
    2984              :     {
    2985            0 :       if (one_cmpl)
    2986            0 :         target = expand_simple_unop (GET_MODE (target), NOT, target,
    2987              :                                      if_info->x, 0);
    2988              :       else
    2989            0 :         target = expand_simple_unop (GET_MODE (target), NEG, target,
    2990              :                                      if_info->x, 0);
    2991              :     }
    2992              : 
    2993           24 :   if (! target)
    2994              :     {
    2995            0 :       end_sequence ();
    2996            0 :       return false;
    2997              :     }
    2998              : 
    2999           24 :   if (target != if_info->x)
    3000            0 :     noce_emit_move_insn (if_info->x, target);
    3001              : 
    3002           24 :   seq = end_ifcvt_sequence (if_info);
    3003           24 :   if (!seq)
    3004              :     return false;
    3005              : 
    3006           24 :   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
    3007           24 :   if_info->cond = cond;
    3008           24 :   if_info->cond_earliest = earliest;
    3009           24 :   if_info->rev_cond = NULL_RTX;
    3010           24 :   if_info->transform_name = "noce_try_abs";
    3011              : 
    3012           24 :   return true;
    3013              : }
    3014              : 
    3015              : /* Convert "if (m < 0) x = b; else x = 0;" to "x = (m >> C) & b;".  */
    3016              : 
    3017              : static bool
    3018       142814 : noce_try_sign_mask (struct noce_if_info *if_info)
    3019              : {
    3020       142814 :   rtx cond, t, m, c;
    3021       142814 :   rtx_insn *seq;
    3022       142814 :   machine_mode mode;
    3023       142814 :   enum rtx_code code;
    3024       142814 :   bool t_unconditional;
    3025              : 
    3026       296186 :   if (!noce_simple_bbs (if_info))
    3027              :     return false;
    3028              : 
    3029       130659 :   cond = if_info->cond;
    3030       130659 :   code = GET_CODE (cond);
    3031       130659 :   m = XEXP (cond, 0);
    3032       130659 :   c = XEXP (cond, 1);
    3033              : 
    3034       130659 :   t = NULL_RTX;
    3035       130659 :   if (if_info->a == const0_rtx)
    3036              :     {
    3037         2396 :       if ((code == LT && c == const0_rtx)
    3038         2359 :           || (code == LE && c == constm1_rtx))
    3039           37 :         t = if_info->b;
    3040              :     }
    3041       128263 :   else if (if_info->b == const0_rtx)
    3042              :     {
    3043        11505 :       if ((code == GE && c == const0_rtx)
    3044        11505 :           || (code == GT && c == constm1_rtx))
    3045              :         t = if_info->a;
    3046              :     }
    3047              : 
    3048          114 :   if (! t || side_effects_p (t))
    3049       130545 :     return false;
    3050              : 
    3051              :   /* We currently don't handle different modes.  */
    3052          114 :   mode = GET_MODE (t);
    3053          114 :   if (GET_MODE (m) != mode)
    3054              :     return false;
    3055              : 
    3056              :   /* This is only profitable if T is unconditionally executed/evaluated in the
    3057              :      original insn sequence or T is cheap and can't trap or fault.  The former
    3058              :      happens if B is the non-zero (T) value and if INSN_B was taken from
    3059              :      TEST_BB, or there was no INSN_B which can happen for e.g. conditional
    3060              :      stores to memory.  For the cost computation use the block TEST_BB where
    3061              :      the evaluation will end up after the transformation.  */
    3062           43 :   t_unconditional
    3063           86 :     = (t == if_info->b
    3064           43 :        && (if_info->insn_b == NULL_RTX
    3065            0 :            || BLOCK_FOR_INSN (if_info->insn_b) == if_info->test_bb));
    3066           86 :   if (!(t_unconditional
    3067           43 :         || ((set_src_cost (t, mode, if_info->speed_p)
    3068              :              < COSTS_N_INSNS (2))
    3069           37 :             && !may_trap_or_fault_p (t))))
    3070           43 :     return false;
    3071              : 
    3072            0 :   if (!noce_can_force_operand (t))
    3073              :     return false;
    3074              : 
    3075            0 :   start_sequence ();
    3076              :   /* Use emit_store_flag to generate "m < 0 ? -1 : 0" instead of expanding
    3077              :      "(signed) m >> 31" directly.  This benefits targets with specialized
    3078              :      insns to obtain the signmask, but still uses ashr_optab otherwise.  */
    3079            0 :   m = emit_store_flag (gen_reg_rtx (mode), LT, m, const0_rtx, mode, 0, -1);
    3080            0 :   t = m ? expand_binop (mode, and_optab, m, t, NULL_RTX, 0, OPTAB_DIRECT)
    3081              :         : NULL_RTX;
    3082              : 
    3083            0 :   if (!t)
    3084              :     {
    3085            0 :       end_sequence ();
    3086            0 :       return false;
    3087              :     }
    3088              : 
    3089            0 :   noce_emit_move_insn (if_info->x, t);
    3090              : 
    3091            0 :   seq = end_ifcvt_sequence (if_info);
    3092            0 :   if (!seq)
    3093              :     return false;
    3094              : 
    3095            0 :   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
    3096            0 :   if_info->transform_name = "noce_try_sign_mask";
    3097              : 
    3098            0 :   return true;
    3099              : }
    3100              : 
    3101              : /*  Check if OP is supported by conditional zero based if conversion,
    3102              :     returning TRUE if satisfied otherwise FALSE.
    3103              : 
    3104              :     OP is the operation to check.  */
    3105              : 
    3106              : static bool
    3107       106795 : noce_cond_zero_binary_op_supported (rtx op)
    3108              : {
    3109       106795 :   enum rtx_code opcode = GET_CODE (op);
    3110              : 
    3111            0 :   if (opcode == PLUS || opcode == MINUS || opcode == IOR || opcode == XOR
    3112              :       || opcode == ASHIFT || opcode == ASHIFTRT || opcode == LSHIFTRT
    3113              :       || opcode == ROTATE || opcode == ROTATERT || opcode == AND)
    3114            0 :     return true;
    3115              : 
    3116              :   return false;
    3117              : }
    3118              : 
    3119              : /*  Helper function to return REG itself,
    3120              :     otherwise NULL_RTX for other RTX_CODE.  */
    3121              : 
    3122              : static rtx
    3123        26921 : get_base_reg (rtx exp)
    3124              : {
    3125            0 :   if (REG_P (exp))
    3126              :     return exp;
    3127         7610 :   else if (SUBREG_P (exp))
    3128            0 :     return SUBREG_REG (exp);
    3129              : 
    3130              :   return NULL_RTX;
    3131              : }
    3132              : 
    3133              : /*  Try to covert if-then-else with conditional zero,
    3134              :     returning TURE on success or FALSE on failure.
    3135              :     IF_INFO describes the if-conversion scenario under consideration.
    3136              : 
    3137              :     It verifies the branch structure on left and transforms it into branchless
    3138              :     sequence on the right, with a backend provided conditional zero or orig for
    3139              :     operand z. If true, tmp is z, 0 otherwise (y op 0 is same as y for most op).
    3140              : 
    3141              :       if (cond)         |  tmp = cond ? z : 0
    3142              :         x = y op z      |    x = y op tmp
    3143              :       else              |
    3144              :         x = y           |
    3145              : 
    3146              :     AND is special as it needs to be handled differently.
    3147              : 
    3148              :       tmp = !cond ? y : 0
    3149              :         x = (y & z) | tmp
    3150              :     Also for AND try:
    3151              :       tmp = cond ? z : -1
    3152              :         x = y op tmp
    3153              :     To see if it is cheaper to produce `!cond ? y : 0`
    3154              :     or `cond ? z : -1`.
    3155              :   */
    3156              : 
    3157              : static int
    3158       176953 : noce_try_cond_arith (struct noce_if_info *if_info)
    3159              : {
    3160       176953 :   rtx target, a, b, a_op0, a_op1;
    3161       176953 :   rtx cond = if_info->cond;
    3162       176953 :   rtx_code code = GET_CODE (cond);
    3163       176953 :   rtx_insn *seq;
    3164       176953 :   rtx_code op;
    3165       176953 :   machine_mode mode = GET_MODE (if_info->x);
    3166              : 
    3167              :   /* Scalar integral modes are only supported here.
    3168              :      Could support scalar floating point but that
    3169              :      would be only with -ffast-math and might
    3170              :      be worse than a branch.  */
    3171       176953 :   if (!SCALAR_INT_MODE_P (mode))
    3172              :     return false;
    3173              : 
    3174       307173 :   if (!noce_simple_bbs (if_info))
    3175              :     return false;
    3176              : 
    3177       105681 :   a = copy_rtx (if_info->a);
    3178       105681 :   b = copy_rtx (if_info->b);
    3179              : 
    3180              :   /* Canonicalize x = y : (y op z) to x = (y op z) : y.  */
    3181       105681 :   if (REG_P (a) && noce_cond_zero_binary_op_supported (b))
    3182              :     {
    3183          251 :       if (if_info->rev_cond)
    3184              :         {
    3185          251 :           cond = if_info->rev_cond;
    3186          251 :           code = GET_CODE (cond);
    3187              :         }
    3188              :       else
    3189            0 :         code = reversed_comparison_code (cond, if_info->jump);
    3190              :       std::swap (a, b);
    3191              :     }
    3192              : 
    3193              :   /* Check if x = (y op z) : y is supported by czero based ifcvt.  */
    3194       105430 :   else if (!(noce_cond_zero_binary_op_supported (a) && REG_P (b)))
    3195        88663 :     goto fail;
    3196              : 
    3197        17018 :   if (code == UNKNOWN)
    3198            0 :     goto fail;
    3199              : 
    3200        17018 :   op = GET_CODE (a);
    3201              : 
    3202              :   /* Canonicalize x = (z op y) : y to x = (y op z) : y */
    3203        17018 :   a_op1 = get_base_reg (XEXP (a, 1));
    3204         9897 :   if (a_op1 && rtx_equal_p (a_op1, b) && COMMUTATIVE_ARITH_P (a))
    3205              :     {
    3206           20 :       std::swap (XEXP (a, 0), XEXP (a, 1));
    3207           20 :       a_op1 = get_base_reg (XEXP (a, 1));
    3208              :     }
    3209              : 
    3210        16998 :   if (a_op1 == NULL_RTX)
    3211         7135 :     goto fail;
    3212              : 
    3213              :   /* Ensure the cond is of form: x = (y op z) : y */
    3214         9883 :   a_op0 = get_base_reg (XEXP (a, 0));
    3215         9874 :   if (!(a_op0 && rtx_equal_p (a_op0, b)))
    3216          800 :     goto fail;
    3217              : 
    3218         9083 :   start_sequence ();
    3219              : 
    3220         9083 :   target = gen_reg_rtx (GET_MODE (XEXP (a, op != AND)));
    3221              : 
    3222              :   /* AND requires !cond, instead we swap ops around.  */
    3223         9083 :   target = noce_emit_cmove (if_info, target, code,
    3224              :                             XEXP (cond, 0), XEXP (cond, 1),
    3225              :                             op != AND ? XEXP (a, 1) : const0_rtx,
    3226              :                             op != AND ? const0_rtx : XEXP (a, 0));
    3227         9083 :   if (!target)
    3228              :     {
    3229          386 :       end_sequence ();
    3230          386 :       rtx tmp = XEXP (a, op != AND);
    3231              :       /* If the cmove fails and this was a lowpart subreg,
    3232              :          then try the reg part and then putting back the lowpart
    3233              :          afterwards.  */
    3234          386 :       if (GET_CODE (tmp) != SUBREG  || !subreg_lowpart_p (tmp))
    3235          386 :         return false;
    3236            0 :       tmp = SUBREG_REG (tmp);
    3237              :       /* Only handle integer scalar modes for the inner mode of
    3238              :          the subreg.  */
    3239            0 :       if (!SCALAR_INT_MODE_P (GET_MODE (tmp)))
    3240              :         return false;
    3241              : 
    3242            0 :       start_sequence ();
    3243            0 :       target = gen_reg_rtx (GET_MODE (tmp));
    3244            0 :       target = noce_emit_cmove (if_info, target, code,
    3245              :                                 XEXP (cond, 0), XEXP (cond, 1),
    3246              :                                 op != AND ? tmp : const0_rtx,
    3247              :                                 op != AND ? const0_rtx : tmp);
    3248            0 :       if (!target)
    3249            0 :         goto end_seq_n_fail;
    3250            0 :       target = rtl_hooks.gen_lowpart_no_emit (GET_MODE (XEXP (a, op != AND)), target);
    3251            0 :       gcc_assert (target);
    3252              :     }
    3253              : 
    3254              :   /* For AND, try `cond ? z : -1` to see if that is cheaper or the same cost.
    3255              :      In some cases it will be cheaper to produce the -1 rather than the 0 case.  */
    3256         8697 :   if (op == AND)
    3257              :     {
    3258            6 :       rtx_insn *seq0 = end_sequence ();
    3259            6 :       unsigned cost0 = seq_cost (seq0, if_info->speed_p);
    3260            6 :       if (!target)
    3261              :         cost0 = -1u;
    3262              : 
    3263              :       /* Produce `cond ? z : -1`. */
    3264            6 :       rtx targetm1;
    3265            6 :       start_sequence ();
    3266            6 :       targetm1 = gen_reg_rtx (GET_MODE (XEXP (a, 1)));
    3267            6 :       targetm1 = noce_emit_cmove (if_info, targetm1, code,
    3268              :                                   XEXP (cond, 0), XEXP (cond, 1),
    3269              :                                   XEXP (a, 1), constm1_rtx);
    3270            6 :       rtx_insn *seqm1 = end_sequence ();
    3271            6 :       unsigned costm1 = seq_cost (seqm1, if_info->speed_p);
    3272            6 :       if (!targetm1)
    3273            0 :         costm1 = -1u;
    3274              :       /* If both fails, then there is no costing to be done. */
    3275            6 :       if (!targetm1 && !target)
    3276              :         return false;
    3277              : 
    3278              :       /* If -1 is cheaper or the same cost to producing 0, then use that.  */
    3279            6 :       if (costm1 <= cost0)
    3280              :         {
    3281            6 :           push_to_sequence (seqm1);
    3282            6 :           targetm1 = expand_simple_binop (mode, op, a_op0, targetm1,
    3283              :                                           if_info->x, 0, OPTAB_WIDEN);
    3284            6 :           if (targetm1)
    3285              :             {
    3286            6 :               target = targetm1;
    3287            6 :               goto success;
    3288              :             }
    3289            0 :           end_sequence ();
    3290              :         }
    3291            0 :       if (!target)
    3292              :         return false;
    3293              :       /* For 0 the produce sequence is:
    3294              :          tmp = !cond ? y : 0
    3295              :          x = (y & z) | tmp  */
    3296            0 :       push_to_sequence (seq0);
    3297            0 :       rtx a_bin = gen_reg_rtx (mode);
    3298            0 :       noce_emit_move_insn (a_bin, a);
    3299              : 
    3300            0 :       target = expand_simple_binop (mode, IOR, a_bin, target, if_info->x, 0,
    3301              :                                     OPTAB_WIDEN);
    3302            0 :       if (!target)
    3303            0 :         goto end_seq_n_fail;
    3304            0 :       goto success;
    3305              :     }
    3306         8691 :   if (!target)
    3307              :     goto end_seq_n_fail;
    3308              : 
    3309         8691 :   target = expand_simple_binop (mode, op, a_op0, target, if_info->x, 0,
    3310              :                                 OPTAB_WIDEN);
    3311              : 
    3312         8691 :   if (!target)
    3313            0 :     goto end_seq_n_fail;
    3314              : 
    3315         8691 : success:
    3316         8697 :   if (target != if_info->x)
    3317            0 :     noce_emit_move_insn (if_info->x, target);
    3318              : 
    3319         8697 :   seq = end_ifcvt_sequence (if_info);
    3320         8697 :   if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
    3321          273 :     goto fail;
    3322              : 
    3323         8424 :   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
    3324         8424 :   if_info->transform_name = "noce_try_cond_arith";
    3325         8424 :   return true;
    3326              : 
    3327            0 : end_seq_n_fail:
    3328            0 :   end_sequence ();
    3329              : 
    3330              : fail:
    3331              : 
    3332              :   return false;
    3333              : }
    3334              : 
    3335              : /* Optimize away "if (x & C) x |= C" and similar bit manipulation
    3336              :    transformations.  */
    3337              : 
    3338              : static bool
    3339       229231 : noce_try_bitop (struct noce_if_info *if_info)
    3340              : {
    3341       229231 :   rtx cond, x, a, result;
    3342       229231 :   rtx_insn *seq;
    3343       229231 :   scalar_int_mode mode;
    3344       229231 :   enum rtx_code code;
    3345       229231 :   int bitnum;
    3346              : 
    3347       229231 :   x = if_info->x;
    3348       229231 :   cond = if_info->cond;
    3349       229231 :   code = GET_CODE (cond);
    3350              : 
    3351              :   /* Check for an integer operation.  */
    3352       229231 :   if (!is_a <scalar_int_mode> (GET_MODE (x), &mode))
    3353              :     return false;
    3354              : 
    3355       433745 :   if (!noce_simple_bbs (if_info))
    3356              :     return false;
    3357              : 
    3358              :   /* Check for no else condition.  */
    3359       152465 :   if (! rtx_equal_p (x, if_info->b))
    3360              :     return false;
    3361              : 
    3362              :   /* Check for a suitable condition.  */
    3363        83061 :   if (code != NE && code != EQ)
    3364              :     return false;
    3365        59821 :   if (XEXP (cond, 1) != const0_rtx)
    3366              :     return false;
    3367        40513 :   cond = XEXP (cond, 0);
    3368              : 
    3369              :   /* ??? We could also handle AND here.  */
    3370        40513 :   if (GET_CODE (cond) == ZERO_EXTRACT)
    3371              :     {
    3372          289 :       if (XEXP (cond, 1) != const1_rtx
    3373          169 :           || !CONST_INT_P (XEXP (cond, 2))
    3374          458 :           || ! rtx_equal_p (x, XEXP (cond, 0)))
    3375          284 :         return false;
    3376            5 :       bitnum = INTVAL (XEXP (cond, 2));
    3377            5 :       if (BITS_BIG_ENDIAN)
    3378              :         bitnum = GET_MODE_BITSIZE (mode) - 1 - bitnum;
    3379            5 :       if (bitnum < 0 || bitnum >= HOST_BITS_PER_WIDE_INT)
    3380              :         return false;
    3381              :     }
    3382              :   else
    3383              :     return false;
    3384              : 
    3385            5 :   a = if_info->a;
    3386            5 :   if (GET_CODE (a) == IOR || GET_CODE (a) == XOR)
    3387              :     {
    3388              :       /* Check for "if (X & C) x = x op C".  */
    3389            0 :       if (! rtx_equal_p (x, XEXP (a, 0))
    3390            0 :           || !CONST_INT_P (XEXP (a, 1))
    3391            0 :           || (INTVAL (XEXP (a, 1)) & GET_MODE_MASK (mode))
    3392            0 :              != HOST_WIDE_INT_1U << bitnum)
    3393              :         return false;
    3394              : 
    3395              :       /* if ((x & C) == 0) x |= C; is transformed to x |= C.   */
    3396              :       /* if ((x & C) != 0) x |= C; is transformed to nothing.  */
    3397            0 :       if (GET_CODE (a) == IOR)
    3398            0 :         result = (code == NE) ? a : NULL_RTX;
    3399            0 :       else if (code == NE)
    3400              :         {
    3401              :           /* if ((x & C) == 0) x ^= C; is transformed to x |= C.   */
    3402            0 :           result = gen_int_mode (HOST_WIDE_INT_1 << bitnum, mode);
    3403            0 :           result = simplify_gen_binary (IOR, mode, x, result);
    3404              :         }
    3405              :       else
    3406              :         {
    3407              :           /* if ((x & C) != 0) x ^= C; is transformed to x &= ~C.  */
    3408            0 :           result = gen_int_mode (~(HOST_WIDE_INT_1 << bitnum), mode);
    3409            0 :           result = simplify_gen_binary (AND, mode, x, result);
    3410              :         }
    3411              :     }
    3412            5 :   else if (GET_CODE (a) == AND)
    3413              :     {
    3414              :       /* Check for "if (X & C) x &= ~C".  */
    3415            0 :       if (! rtx_equal_p (x, XEXP (a, 0))
    3416            0 :           || !CONST_INT_P (XEXP (a, 1))
    3417            0 :           || (INTVAL (XEXP (a, 1)) & GET_MODE_MASK (mode))
    3418            0 :              != (~(HOST_WIDE_INT_1 << bitnum) & GET_MODE_MASK (mode)))
    3419              :         return false;
    3420              : 
    3421              :       /* if ((x & C) == 0) x &= ~C; is transformed to nothing.  */
    3422              :       /* if ((x & C) != 0) x &= ~C; is transformed to x &= ~C.  */
    3423            0 :       result = (code == EQ) ? a : NULL_RTX;
    3424              :     }
    3425              :   else
    3426              :     return false;
    3427              : 
    3428            0 :   if (result)
    3429              :     {
    3430            0 :       start_sequence ();
    3431            0 :       noce_emit_move_insn (x, result);
    3432            0 :       seq = end_ifcvt_sequence (if_info);
    3433            0 :       if (!seq)
    3434              :         return false;
    3435              : 
    3436            0 :       emit_insn_before_setloc (seq, if_info->jump,
    3437            0 :                                INSN_LOCATION (if_info->insn_a));
    3438              :     }
    3439            0 :   if_info->transform_name = "noce_try_bitop";
    3440            0 :   return true;
    3441              : }
    3442              : 
    3443              : 
    3444              : /* Similar to get_condition, only the resulting condition must be
    3445              :    valid at JUMP, instead of at EARLIEST.
    3446              : 
    3447              :    If THEN_ELSE_REVERSED is true, the fallthrough does not go to the
    3448              :    THEN block of the caller, and we have to reverse the condition.  */
    3449              : 
    3450              : static rtx
    3451      4297304 : noce_get_condition (rtx_insn *jump, rtx_insn **earliest,
    3452              :                     bool then_else_reversed)
    3453              : {
    3454      4297304 :   rtx cond, set, tmp;
    3455      4297304 :   bool reverse;
    3456              : 
    3457      4297304 :   if (! any_condjump_p (jump))
    3458              :     return NULL_RTX;
    3459              : 
    3460      4297304 :   set = pc_set (jump);
    3461              : 
    3462              :   /* If this branches to JUMP_LABEL when the condition is false,
    3463              :      reverse the condition.  */
    3464      8594608 :   reverse = (GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
    3465      4297304 :              && label_ref_label (XEXP (SET_SRC (set), 2)) == JUMP_LABEL (jump));
    3466              : 
    3467              :   /* We may have to reverse because the caller's if block is not canonical,
    3468              :      i.e. the THEN block isn't the fallthrough block for the TEST block
    3469              :      (see find_if_header).  */
    3470      4297304 :   if (then_else_reversed)
    3471      1881698 :     reverse = !reverse;
    3472              : 
    3473              :   /* If the condition variable is a register and is MODE_INT, accept it.  */
    3474              : 
    3475      4297304 :   cond = XEXP (SET_SRC (set), 0);
    3476      4297304 :   tmp = XEXP (cond, 0);
    3477      4296353 :   if (REG_P (tmp) && GET_MODE_CLASS (GET_MODE (tmp)) == MODE_INT
    3478      4297346 :       && (GET_MODE (tmp) != BImode
    3479            0 :           || !targetm.small_register_classes_for_mode_p (BImode)))
    3480              :     {
    3481           42 :       *earliest = jump;
    3482              : 
    3483           42 :       if (reverse)
    3484           18 :         cond = gen_rtx_fmt_ee (reverse_condition (GET_CODE (cond)),
    3485              :                                GET_MODE (cond), tmp, XEXP (cond, 1));
    3486           42 :       return cond;
    3487              :     }
    3488              : 
    3489              :   /* Otherwise, fall back on canonicalize_condition to do the dirty
    3490              :      work of manipulating MODE_CC values and COMPARE rtx codes.  */
    3491      4297262 :   tmp = canonicalize_condition (jump, cond, reverse, earliest,
    3492              :                                 NULL_RTX, have_cbranchcc4, true);
    3493              : 
    3494              :   /* We don't handle side-effects in the condition, like handling
    3495              :      REG_INC notes and making sure no duplicate conditions are emitted.  */
    3496      4297262 :   if (tmp != NULL_RTX && side_effects_p (tmp))
    3497              :     return NULL_RTX;
    3498              : 
    3499              :   return tmp;
    3500              : }
    3501              : 
    3502              : /* Return true if OP is ok for if-then-else processing.  */
    3503              : 
    3504              : static bool
    3505      8966179 : noce_operand_ok (const_rtx op)
    3506              : {
    3507      8966179 :   if (side_effects_p (op))
    3508              :     return false;
    3509              : 
    3510              :   /* We special-case memories, so handle any of them with
    3511              :      no address side effects.  */
    3512      8945618 :   if (MEM_P (op))
    3513      1577429 :     return ! side_effects_p (XEXP (op, 0));
    3514              : 
    3515      7368189 :   return ! may_trap_p (op);
    3516              : }
    3517              : 
    3518              : /* Return true iff basic block TEST_BB is valid for noce if-conversion.
    3519              :    The condition used in this if-conversion is in COND.
    3520              :    In practice, check that TEST_BB ends with a single set
    3521              :    x := a and all previous computations
    3522              :    in TEST_BB don't produce any values that are live after TEST_BB.
    3523              :    In other words, all the insns in TEST_BB are there only
    3524              :    to compute a value for x.  Add the rtx cost of the insns
    3525              :    in TEST_BB to COST.  Record whether TEST_BB is a single simple
    3526              :    set instruction in SIMPLE_P.  */
    3527              : 
    3528              : static bool
    3529      2147091 : bb_valid_for_noce_process_p (basic_block test_bb, rtx cond,
    3530              :                               unsigned int *cost, bool *simple_p)
    3531              : {
    3532      2147091 :   if (!test_bb)
    3533              :     return false;
    3534              : 
    3535      2147091 :   rtx_insn *last_insn = last_active_insn (test_bb, false);
    3536      2147091 :   rtx last_set = NULL_RTX;
    3537              : 
    3538      2147091 :   rtx cc = cc_in_cond (cond);
    3539              : 
    3540      2147091 :   if (!insn_valid_noce_process_p (last_insn, cc))
    3541              :     return false;
    3542              : 
    3543              :   /* Punt on blocks ending with asm goto or jumps with other side-effects,
    3544              :      last_active_insn ignores JUMP_INSNs.  */
    3545      1545451 :   if (JUMP_P (BB_END (test_bb)) && !onlyjump_p (BB_END (test_bb)))
    3546              :     return false;
    3547              : 
    3548      1545449 :   last_set = single_set (last_insn);
    3549              : 
    3550      1545449 :   rtx x = SET_DEST (last_set);
    3551      1545449 :   rtx_insn *first_insn = first_active_insn (test_bb);
    3552      1545449 :   rtx first_set = single_set (first_insn);
    3553              : 
    3554      1545449 :   if (!first_set)
    3555              :     return false;
    3556              : 
    3557              :   /* We have a single simple set, that's okay.  */
    3558      1531692 :   bool speed_p = optimize_bb_for_speed_p (test_bb);
    3559              : 
    3560      1531692 :   if (first_insn == last_insn)
    3561              :     {
    3562       567693 :       *simple_p = noce_operand_ok (SET_DEST (first_set));
    3563       567693 :       *cost += pattern_cost (first_set, speed_p);
    3564       567693 :       return *simple_p;
    3565              :     }
    3566              : 
    3567       963999 :   rtx_insn *prev_last_insn = PREV_INSN (last_insn);
    3568       963999 :   gcc_assert (prev_last_insn);
    3569              : 
    3570              :   /* For now, disallow setting x multiple times in test_bb.  */
    3571       963999 :   if (REG_P (x) && reg_set_between_p (x, first_insn, prev_last_insn))
    3572              :     return false;
    3573              : 
    3574       818213 :   bitmap test_bb_temps = BITMAP_ALLOC (&reg_obstack);
    3575              : 
    3576              :   /* The regs that are live out of test_bb.  */
    3577       818213 :   bitmap test_bb_live_out = df_get_live_out (test_bb);
    3578              : 
    3579       818213 :   int potential_cost = pattern_cost (last_set, speed_p);
    3580       818213 :   rtx_insn *insn;
    3581      4338916 :   FOR_BB_INSNS (test_bb, insn)
    3582              :     {
    3583      4226269 :       if (insn != last_insn)
    3584              :         {
    3585      4113622 :           if (!active_insn_p (insn))
    3586      2673786 :             continue;
    3587              : 
    3588      1439836 :           if (!insn_valid_noce_process_p (insn, cc))
    3589       197000 :             goto free_bitmap_and_fail;
    3590              : 
    3591      1242836 :           rtx sset = single_set (insn);
    3592      1242836 :           gcc_assert (sset);
    3593      1242836 :           rtx dest = SET_DEST (sset);
    3594      1242836 :           if (SUBREG_P (dest))
    3595        17948 :             dest = SUBREG_REG (dest);
    3596              : 
    3597      1242836 :           if (contains_mem_rtx_p (SET_SRC (sset))
    3598       879281 :               || !REG_P (dest)
    3599      1996071 :               || reg_overlap_mentioned_p (dest, cond))
    3600       508566 :             goto free_bitmap_and_fail;
    3601              : 
    3602       734270 :           potential_cost += pattern_cost (sset, speed_p);
    3603       734270 :           bitmap_set_bit (test_bb_temps, REGNO (dest));
    3604              :         }
    3605              :     }
    3606              : 
    3607              :   /* If any of the intermediate results in test_bb are live after test_bb
    3608              :      then fail.  */
    3609       112647 :   if (bitmap_intersect_p (test_bb_live_out, test_bb_temps))
    3610        81232 :     goto free_bitmap_and_fail;
    3611              : 
    3612        31415 :   BITMAP_FREE (test_bb_temps);
    3613        31415 :   *cost += potential_cost;
    3614        31415 :   *simple_p = false;
    3615        31415 :   return true;
    3616              : 
    3617       786798 :  free_bitmap_and_fail:
    3618       786798 :   BITMAP_FREE (test_bb_temps);
    3619       786798 :   return false;
    3620              : }
    3621              : 
    3622              : /* Helper function to emit a cmov sequence encapsulated in
    3623              :    start_sequence () and end_sequence ().  If NEED_CMOV is true
    3624              :    we call noce_emit_cmove to create a cmove sequence.  Otherwise emit
    3625              :    a simple move.  If successful, store the first instruction of the
    3626              :    sequence in TEMP_DEST and the sequence costs in SEQ_COST.  */
    3627              : 
    3628              : static rtx_insn*
    3629       275290 : try_emit_cmove_seq (struct noce_if_info *if_info, rtx temp,
    3630              :                     rtx cond, rtx new_val, rtx old_val, bool need_cmov,
    3631              :                     unsigned *cost, rtx *temp_dest,
    3632              :                     rtx cc_cmp = NULL, rtx rev_cc_cmp = NULL)
    3633              : {
    3634       275290 :   rtx_insn *seq = NULL;
    3635       275290 :   *cost = 0;
    3636              : 
    3637       275290 :   rtx x = XEXP (cond, 0);
    3638       275290 :   rtx y = XEXP (cond, 1);
    3639       275290 :   rtx_code cond_code = GET_CODE (cond);
    3640              : 
    3641       275290 :   start_sequence ();
    3642              : 
    3643       275290 :   if (need_cmov)
    3644       219639 :     *temp_dest = noce_emit_cmove (if_info, temp, cond_code,
    3645              :                                   x, y, new_val, old_val, cc_cmp, rev_cc_cmp);
    3646              :   else
    3647              :     {
    3648        55651 :       *temp_dest = temp;
    3649        55651 :       if (if_info->then_else_reversed)
    3650         2010 :         noce_emit_move_insn (temp, old_val);
    3651              :       else
    3652        53641 :         noce_emit_move_insn (temp, new_val);
    3653              :     }
    3654              : 
    3655       275290 :   if (*temp_dest != NULL_RTX)
    3656              :     {
    3657       269378 :       seq = get_insns ();
    3658       269378 :       *cost = seq_cost (seq, if_info->speed_p);
    3659              :     }
    3660              : 
    3661       275290 :   end_sequence ();
    3662              : 
    3663       275290 :   return seq;
    3664              : }
    3665              : 
    3666              : /* We have something like:
    3667              : 
    3668              :      if (x > y)
    3669              :        { i = EXPR_A; j = EXPR_B; k = EXPR_C; }
    3670              : 
    3671              :    Make it:
    3672              : 
    3673              :      tmp_i = (x > y) ? EXPR_A : i;
    3674              :      tmp_j = (x > y) ? EXPR_B : j;
    3675              :      tmp_k = (x > y) ? EXPR_C : k;
    3676              :      i = tmp_i;
    3677              :      j = tmp_j;
    3678              :      k = tmp_k;
    3679              : 
    3680              :    Subsequent passes are expected to clean up the extra moves.
    3681              : 
    3682              :    Look for special cases such as writes to one register which are
    3683              :    read back in another SET, as might occur in a swap idiom or
    3684              :    similar.
    3685              : 
    3686              :    These look like:
    3687              : 
    3688              :    if (x > y)
    3689              :      i = a;
    3690              :      j = i;
    3691              : 
    3692              :    Which we want to rewrite to:
    3693              : 
    3694              :      tmp_i = (x > y) ? a : i;
    3695              :      tmp_j = (x > y) ? tmp_i : j;
    3696              :      i = tmp_i;
    3697              :      j = tmp_j;
    3698              : 
    3699              :    We can catch these when looking at (SET x y) by keeping a list of the
    3700              :    registers we would have targeted before if-conversion and looking back
    3701              :    through it for an overlap with Y.  If we find one, we rewire the
    3702              :    conditional set to use the temporary we introduced earlier.
    3703              : 
    3704              :    IF_INFO contains the useful information about the block structure and
    3705              :    jump instructions.  */
    3706              : 
    3707              : static bool
    3708        31020 : noce_convert_multiple_sets (struct noce_if_info *if_info)
    3709              : {
    3710        31020 :   basic_block test_bb = if_info->test_bb;
    3711        31020 :   basic_block then_bb = if_info->then_bb;
    3712        31020 :   basic_block join_bb = if_info->join_bb;
    3713        31020 :   rtx_insn *jump = if_info->jump;
    3714        31020 :   rtx_insn *cond_earliest;
    3715        31020 :   rtx_insn *insn;
    3716              : 
    3717        31020 :   start_sequence ();
    3718              : 
    3719              :   /* Decompose the condition attached to the jump.  */
    3720        31020 :   rtx cond = noce_get_condition (jump, &cond_earliest, false);
    3721        31020 :   rtx x = XEXP (cond, 0);
    3722        31020 :   rtx y = XEXP (cond, 1);
    3723              : 
    3724        31020 :   auto_delete_vec<noce_multiple_sets_info> insn_info;
    3725        31020 :   init_noce_multiple_sets_info (then_bb, insn_info);
    3726              : 
    3727        31020 :   int last_needs_comparison = -1;
    3728              : 
    3729        31020 :   bool use_cond_earliest = false;
    3730              : 
    3731        31020 :   bool ok = noce_convert_multiple_sets_1
    3732        31020 :     (if_info, insn_info, &last_needs_comparison, &use_cond_earliest);
    3733        31020 :   if (!ok)
    3734              :       return false;
    3735              : 
    3736              :   /* Always perform a second attempt that uses information gathered in the
    3737              :      first.  At least we can omit creating temporaries until we definitely
    3738              :      need them.  The sequence created in the second attempt is never worse
    3739              :      than the first.  */
    3740              : 
    3741        30064 :   end_sequence ();
    3742        30064 :   start_sequence ();
    3743        30064 :   ok = noce_convert_multiple_sets_1
    3744        30064 :     (if_info, insn_info, &last_needs_comparison, &use_cond_earliest);
    3745              : 
    3746              :   /* Actually we should not fail anymore if we reached here,
    3747              :      but better still check.  */
    3748        30064 :   if (!ok)
    3749              :     return false;
    3750              : 
    3751              :   /* We must have seen some sort of insn to insert, otherwise we were
    3752              :      given an empty BB to convert, and we can't handle that.  */
    3753        30064 :   gcc_assert (!insn_info.is_empty ());
    3754              : 
    3755              :   /* Now fixup the assignments.
    3756              :      PR116405: Iterate in reverse order and keep track of the targets so that
    3757              :      a move does not overwrite a subsequent value when multiple instructions
    3758              :      have the same target.  */
    3759        30064 :   unsigned i;
    3760        30064 :   noce_multiple_sets_info *info;
    3761        30064 :   bitmap set_targets = BITMAP_ALLOC (&reg_obstack);
    3762       112187 :   FOR_EACH_VEC_ELT_REVERSE (insn_info, i, info)
    3763              :     {
    3764        82123 :       gcc_checking_assert (REG_P (info->target));
    3765              : 
    3766        82123 :       if (info->target != info->temporary
    3767        82123 :           && !bitmap_bit_p (set_targets, REGNO (info->target)))
    3768         3173 :         noce_emit_move_insn (info->target, info->temporary);
    3769              : 
    3770        82123 :       bitmap_set_bit (set_targets, REGNO (info->target));
    3771              :     }
    3772        30064 :   BITMAP_FREE (set_targets);
    3773              : 
    3774              :   /* Actually emit the sequence if it isn't too expensive.  */
    3775        30064 :   rtx_insn *seq = get_insns ();
    3776              : 
    3777              :   /* If the created sequence does not use cond_earliest (but the jump
    3778              :      does) add its cost to the original_cost before comparing costs.  */
    3779        30064 :   unsigned int original_cost = if_info->original_cost;
    3780        30064 :   if (if_info->jump != if_info->cond_earliest && !use_cond_earliest)
    3781        19045 :     if_info->original_cost += insn_cost (if_info->cond_earliest,
    3782        19045 :                                          if_info->speed_p);
    3783              : 
    3784        30064 :   if (!targetm.noce_conversion_profitable_p (seq, if_info))
    3785              :     {
    3786         4678 :       end_sequence ();
    3787         4678 :       return false;
    3788              :     }
    3789              : 
    3790              :   /* Restore the original cost in case we do not succeed below.  */
    3791        25386 :   if_info->original_cost = original_cost;
    3792              : 
    3793       148276 :   for (insn = seq; insn; insn = NEXT_INSN (insn))
    3794       122890 :     set_used_flags (insn);
    3795              : 
    3796              :   /* Mark all our temporaries and targets as used.  */
    3797        91031 :   for (unsigned i = 0; i < insn_info.length (); i++)
    3798              :     {
    3799        65645 :       set_used_flags (insn_info[i]->temporary);
    3800        65645 :       set_used_flags (insn_info[i]->target);
    3801              :     }
    3802              : 
    3803        25386 :   set_used_flags (cond);
    3804        25386 :   set_used_flags (x);
    3805        25386 :   set_used_flags (y);
    3806              : 
    3807        25386 :   unshare_all_rtl_in_chain (seq);
    3808        25386 :   end_sequence ();
    3809              : 
    3810        25386 :   if (!seq)
    3811              :     return false;
    3812              : 
    3813       148125 :   for (insn = seq; insn; insn = NEXT_INSN (insn))
    3814       122777 :     if (JUMP_P (insn) || CALL_P (insn)
    3815       122777 :         || recog_memoized (insn) == -1)
    3816           38 :       return false;
    3817              : 
    3818        25348 :   emit_insn_before_setloc (seq, if_info->jump,
    3819        25348 :                            INSN_LOCATION (insn_info.last ()->unmodified_insn));
    3820              : 
    3821              :   /* Clean up THEN_BB and the edges in and out of it.  */
    3822        25348 :   remove_edge (find_edge (test_bb, join_bb));
    3823        25348 :   remove_edge (find_edge (then_bb, join_bb));
    3824        25348 :   redirect_edge_and_branch_force (single_succ_edge (test_bb), join_bb);
    3825        25348 :   delete_basic_block (then_bb);
    3826        25348 :   num_true_changes++;
    3827              : 
    3828              :   /* Maybe merge blocks now the jump is simple enough.  */
    3829        25348 :   if (can_merge_blocks_p (test_bb, join_bb))
    3830              :     {
    3831        16860 :       merge_blocks (test_bb, join_bb);
    3832        16860 :       num_true_changes++;
    3833              :     }
    3834              : 
    3835        25348 :   num_updated_if_blocks++;
    3836        25348 :   if_info->transform_name = "noce_convert_multiple_sets";
    3837        25348 :   return true;
    3838        31020 : }
    3839              : 
    3840              : /* This goes through all relevant insns of IF_INFO->then_bb and tries to create
    3841              :    conditional moves.  Information for the insns is kept in INSN_INFO.  */
    3842              : 
    3843              : static bool
    3844        61084 : noce_convert_multiple_sets_1 (struct noce_if_info *if_info,
    3845              :                               auto_delete_vec<noce_multiple_sets_info> &insn_info,
    3846              :                               int *last_needs_comparison,
    3847              :                               bool *use_cond_earliest)
    3848              : {
    3849        61084 :   basic_block then_bb = if_info->then_bb;
    3850        61084 :   rtx_insn *jump = if_info->jump;
    3851        61084 :   rtx_insn *cond_earliest;
    3852              : 
    3853              :   /* Decompose the condition attached to the jump.  */
    3854        61084 :   rtx cond = noce_get_condition (jump, &cond_earliest, false);
    3855              : 
    3856        61084 :   rtx cc_cmp = cond_exec_get_condition (jump);
    3857        61084 :   if (cc_cmp)
    3858        61084 :     cc_cmp = copy_rtx (cc_cmp);
    3859        61084 :   rtx rev_cc_cmp = cond_exec_get_condition (jump, /* get_reversed */ true);
    3860        61084 :   if (rev_cc_cmp)
    3861        61084 :     rev_cc_cmp = copy_rtx (rev_cc_cmp);
    3862              : 
    3863        61084 :   rtx_insn *insn;
    3864        61084 :   int count = 0;
    3865        61084 :   bool second_try = *last_needs_comparison != -1;
    3866        61084 :   *use_cond_earliest = false;
    3867              : 
    3868       365799 :   FOR_BB_INSNS (then_bb, insn)
    3869              :     {
    3870              :       /* Skip over non-insns.  */
    3871       305671 :       if (!active_insn_p (insn))
    3872       138978 :         continue;
    3873              : 
    3874       166693 :       noce_multiple_sets_info *info = insn_info[count];
    3875              : 
    3876       166693 :       rtx set = single_set (insn);
    3877       166693 :       gcc_checking_assert (set);
    3878              : 
    3879       166693 :       rtx target = SET_DEST (set);
    3880       166693 :       rtx temp;
    3881              : 
    3882       166693 :       rtx new_val = SET_SRC (set);
    3883              : 
    3884       166693 :       int i, ii;
    3885       208975 :       FOR_EACH_VEC_ELT (info->rewired_src, i, ii)
    3886        42282 :         new_val = simplify_replace_rtx (new_val, insn_info[ii]->target,
    3887        42282 :                                         insn_info[ii]->temporary);
    3888              : 
    3889       166693 :       rtx old_val = target;
    3890              : 
    3891              :       /* As we are transforming
    3892              :          if (x > y)
    3893              :            {
    3894              :              a = b;
    3895              :              c = d;
    3896              :            }
    3897              :          into
    3898              :            a = (x > y) ...
    3899              :            c = (x > y) ...
    3900              : 
    3901              :          we potentially check x > y before every set.
    3902              :          Even though the check might be removed by subsequent passes, this means
    3903              :          that we cannot transform
    3904              :            if (x > y)
    3905              :              {
    3906              :                x = y;
    3907              :                ...
    3908              :              }
    3909              :          into
    3910              :            x = (x > y) ...
    3911              :            ...
    3912              :          since this would invalidate x and the following to-be-removed checks.
    3913              :          Therefore we introduce a temporary every time we are about to
    3914              :          overwrite a variable used in the check.  Costing of a sequence with
    3915              :          these is going to be inaccurate so only use temporaries when
    3916              :          needed.
    3917              : 
    3918              :          If performing a second try, we know how many insns require a
    3919              :          temporary.  For the last of these, we can omit creating one.  */
    3920       166693 :       if (reg_overlap_mentioned_p (target, cond)
    3921       166693 :           && (!second_try || count < *last_needs_comparison))
    3922        21337 :         temp = gen_reg_rtx (GET_MODE (target));
    3923              :       else
    3924              :         temp = target;
    3925              : 
    3926              :       /* We have identified swap-style idioms before.  A normal
    3927              :          set will need to be a cmov while the first instruction of a swap-style
    3928              :          idiom can be a regular move.  This helps with costing.  */
    3929       166693 :       bool need_cmov = info->need_cmov;
    3930              : 
    3931              :       /* If we had a non-canonical conditional jump (i.e. one where
    3932              :          the fallthrough is to the "else" case) we need to reverse
    3933              :          the conditional select.  */
    3934       166693 :       if (if_info->then_else_reversed)
    3935        51468 :         std::swap (old_val, new_val);
    3936              : 
    3937              :       /* Try emitting a conditional move passing the backend the
    3938              :          canonicalized comparison.  The backend is then able to
    3939              :          recognize expressions like
    3940              : 
    3941              :            if (x > y)
    3942              :              y = x;
    3943              : 
    3944              :          as min/max and emit an insn, accordingly.  */
    3945       166693 :       unsigned cost1 = 0, cost2 = 0;
    3946       166693 :       rtx_insn *seq, *seq1, *seq2 = NULL;
    3947       166693 :       rtx temp_dest = NULL_RTX, temp_dest1 = NULL_RTX, temp_dest2 = NULL_RTX;
    3948       166693 :       bool read_comparison = false;
    3949              : 
    3950       166693 :       seq1 = try_emit_cmove_seq (if_info, temp, cond,
    3951              :                                  new_val, old_val, need_cmov,
    3952              :                                  &cost1, &temp_dest1);
    3953              : 
    3954              :       /* Here, we try to pass the backend a non-canonicalized cc comparison
    3955              :          as well.  This allows the backend to emit a cmov directly without
    3956              :          creating an additional compare for each.  If successful, costing
    3957              :          is easier and this sequence is usually preferred.  */
    3958       166693 :       if (cc_cmp)
    3959              :         {
    3960       108597 :           seq2 = try_emit_cmove_seq (if_info, temp, cond,
    3961              :                                      new_val, old_val, need_cmov,
    3962              :                                      &cost2, &temp_dest2, cc_cmp, rev_cc_cmp);
    3963              : 
    3964              :           /* The if_then_else in SEQ2 may be affected when cc_cmp/rev_cc_cmp is
    3965              :              clobbered.  We can't safely use the sequence in this case.  */
    3966       190187 :           for (rtx_insn *iter = seq2; iter; iter = NEXT_INSN (iter))
    3967       121045 :             if (modified_in_p (cc_cmp, iter)
    3968       121045 :               || (rev_cc_cmp && modified_in_p (rev_cc_cmp, iter)))
    3969              :               {
    3970              :                 seq2 = NULL;
    3971              :                 break;
    3972              :               }
    3973              :         }
    3974              : 
    3975              :       /* The backend might have created a sequence that uses the
    3976              :          condition as a value.  Check this.  */
    3977              : 
    3978              :       /* We cannot handle anything more complex than a reg or constant.  */
    3979       166693 :       if (!REG_P (XEXP (cond, 0)) && !CONSTANT_P (XEXP (cond, 0)))
    3980       166693 :         read_comparison = true;
    3981              : 
    3982       166693 :       if (!REG_P (XEXP (cond, 1)) && !CONSTANT_P (XEXP (cond, 1)))
    3983       166693 :         read_comparison = true;
    3984              : 
    3985              :       rtx_insn *walk = seq2;
    3986              :       int if_then_else_count = 0;
    3987       245160 :       while (walk && !read_comparison)
    3988              :         {
    3989        78467 :           rtx exprs_to_check[2];
    3990        78467 :           unsigned int exprs_count = 0;
    3991              : 
    3992        78467 :           rtx set = single_set (walk);
    3993        78467 :           if (set && XEXP (set, 1)
    3994        78467 :               && GET_CODE (XEXP (set, 1)) == IF_THEN_ELSE)
    3995              :             {
    3996              :               /* We assume that this is the cmove created by the backend that
    3997              :                  naturally uses the condition.  */
    3998        50032 :               exprs_to_check[exprs_count++] = XEXP (XEXP (set, 1), 1);
    3999        50032 :               exprs_to_check[exprs_count++] = XEXP (XEXP (set, 1), 2);
    4000        50032 :               if_then_else_count++;
    4001              :             }
    4002        28435 :           else if (NONDEBUG_INSN_P (walk))
    4003        28435 :             exprs_to_check[exprs_count++] = PATTERN (walk);
    4004              : 
    4005              :           /* Bail if we get more than one if_then_else because the assumption
    4006              :              above may be incorrect.  */
    4007        78467 :           if (if_then_else_count > 1)
    4008              :             {
    4009            0 :               read_comparison = true;
    4010            0 :               break;
    4011              :             }
    4012              : 
    4013       206966 :           for (unsigned int i = 0; i < exprs_count; i++)
    4014              :             {
    4015       128499 :               subrtx_iterator::array_type array;
    4016       284595 :               FOR_EACH_SUBRTX (iter, array, exprs_to_check[i], NONCONST)
    4017       186612 :                 if (*iter != NULL_RTX
    4018       186612 :                     && (reg_overlap_mentioned_p (XEXP (cond, 0), *iter)
    4019       168920 :                     || reg_overlap_mentioned_p (XEXP (cond, 1), *iter)))
    4020              :                   {
    4021              :                     read_comparison = true;
    4022              :                     break;
    4023              :                   }
    4024       128499 :             }
    4025              : 
    4026        78467 :           walk = NEXT_INSN (walk);
    4027              :         }
    4028              : 
    4029              :       /* Check which version is less expensive.  */
    4030       166693 :       if (seq1 != NULL_RTX && (cost1 <= cost2 || seq2 == NULL_RTX))
    4031              :         {
    4032       114943 :           seq = seq1;
    4033       114943 :           temp_dest = temp_dest1;
    4034       114943 :           if (!second_try)
    4035        58281 :             *last_needs_comparison = count;
    4036              :         }
    4037          937 :       else if (seq2 != NULL_RTX)
    4038              :         {
    4039        50951 :           seq = seq2;
    4040        50951 :           temp_dest = temp_dest2;
    4041        50951 :           if (!second_try && read_comparison)
    4042         8318 :             *last_needs_comparison = count;
    4043        50951 :           *use_cond_earliest = true;
    4044              :         }
    4045              :       else
    4046              :         {
    4047              :           /* Nothing worked, bail out.  */
    4048          799 :           end_sequence ();
    4049          956 :           return false;
    4050              :         }
    4051              : 
    4052              :       /* Although we use temporaries if there is register overlap of COND and
    4053              :          TARGET, it is possible that SEQ modifies COND anyway.  For example,
    4054              :          COND may use the flags register and if INSN clobbers flags then
    4055              :          we may be unable to emit a valid sequence (e.g. in x86 that would
    4056              :          require saving and restoring the flags register).  */
    4057       109232 :       if (!second_try)
    4058       247594 :         for (rtx_insn *iter = seq; iter; iter = NEXT_INSN (iter))
    4059       163980 :           if (modified_in_p (cond, iter))
    4060              :             {
    4061          157 :               end_sequence ();
    4062          157 :               return false;
    4063              :             }
    4064              : 
    4065       165737 :       if (cc_cmp && seq == seq1)
    4066              :         {
    4067              :           /* Check if SEQ can clobber registers mentioned in cc_cmp/rev_cc_cmp.
    4068              :              If yes, we need to use only SEQ1 from that point on.
    4069              :              Only check when we use SEQ1 since we have already tested SEQ2.  */
    4070        78095 :           for (rtx_insn *iter = seq; iter; iter = NEXT_INSN (iter))
    4071        60073 :             if (modified_in_p (cc_cmp, iter)
    4072        60073 :               || (rev_cc_cmp && modified_in_p (rev_cc_cmp, iter)))
    4073              :               {
    4074              :                 cc_cmp = NULL_RTX;
    4075              :                 rev_cc_cmp = NULL_RTX;
    4076              :                 break;
    4077              :               }
    4078              :         }
    4079              : 
    4080              :       /* End the sub sequence and emit to the main sequence.  */
    4081       165737 :       emit_insn (seq);
    4082              : 
    4083              :       /* Bookkeeping.  */
    4084       165737 :       count++;
    4085              : 
    4086       165737 :       info->target = target;
    4087       165737 :       info->temporary = temp_dest;
    4088       165737 :       info->unmodified_insn = insn;
    4089              :     }
    4090              : 
    4091              :   /* Even if we did not actually need the comparison, we want to make sure
    4092              :      to try a second time in order to get rid of the temporaries.  */
    4093        60128 :   if (*last_needs_comparison == -1)
    4094         1073 :     *last_needs_comparison = 0;
    4095              : 
    4096              :   return true;
    4097              : }
    4098              : 
    4099              : /* Find local swap-style idioms in BB and mark the first insn (1)
    4100              :    that is only a temporary as not needing a conditional move as
    4101              :    it is going to be dead afterwards anyway.
    4102              : 
    4103              :      (1) int tmp = a;
    4104              :          a = b;
    4105              :          b = tmp;
    4106              : 
    4107              :          ifcvt
    4108              :          -->
    4109              : 
    4110              :          tmp = a;
    4111              :          a = cond ? b : a_old;
    4112              :          b = cond ? tmp : b_old;
    4113              : 
    4114              :     Additionally, store the index of insns like (2) when a subsequent
    4115              :     SET reads from their destination.
    4116              : 
    4117              :     (2) int c = a;
    4118              :         int d = c;
    4119              : 
    4120              :         ifcvt
    4121              :         -->
    4122              : 
    4123              :         c = cond ? a : c_old;
    4124              :         d = cond ? d : c;     // Need to use c rather than c_old here.
    4125              : */
    4126              : 
    4127              : static void
    4128        31020 : init_noce_multiple_sets_info (basic_block bb,
    4129              :                      auto_delete_vec<noce_multiple_sets_info> &insn_info)
    4130              : {
    4131        31020 :   rtx_insn *insn;
    4132        31020 :   int count = 0;
    4133        31020 :   auto_vec<rtx> dests;
    4134        31020 :   bitmap bb_live_out = df_get_live_out (bb);
    4135              : 
    4136              :   /* Iterate over all SETs, storing the destinations in DEST.
    4137              :      - If we encounter a previously changed register,
    4138              :        rewire the read to the original source.
    4139              :      - If we encounter a SET that writes to a destination
    4140              :         that is not live after this block then the register
    4141              :         does not need to be moved conditionally.  */
    4142       186992 :   FOR_BB_INSNS (bb, insn)
    4143              :     {
    4144       155972 :       if (!active_insn_p (insn))
    4145        71021 :         continue;
    4146              : 
    4147        84951 :       noce_multiple_sets_info *info = new noce_multiple_sets_info;
    4148        84951 :       info->target = NULL_RTX;
    4149        84951 :       info->temporary = NULL_RTX;
    4150        84951 :       info->unmodified_insn = NULL;
    4151        84951 :       insn_info.safe_push (info);
    4152              : 
    4153        84951 :       rtx set = single_set (insn);
    4154        84951 :       gcc_checking_assert (set);
    4155              : 
    4156        84951 :       rtx src = SET_SRC (set);
    4157        84951 :       rtx dest = SET_DEST (set);
    4158              : 
    4159        84951 :       gcc_checking_assert (REG_P (dest));
    4160        84951 :       info->need_cmov = bitmap_bit_p (bb_live_out, REGNO (dest));
    4161              : 
    4162              :       /* Check if the current SET's source is the same
    4163              :          as any previously seen destination.
    4164              :          This is quadratic but the number of insns in BB
    4165              :          is bounded by PARAM_MAX_RTL_IF_CONVERSION_INSNS.  */
    4166       185887 :       for (int i = count - 1; i >= 0; --i)
    4167       100936 :         if (reg_mentioned_p (dests[i], src))
    4168        21944 :           insn_info[count]->rewired_src.safe_push (i);
    4169              : 
    4170        84951 :       dests.safe_push (dest);
    4171        84951 :       count++;
    4172              :     }
    4173        31020 : }
    4174              : 
    4175              : /* Return true iff basic block TEST_BB is suitable for conversion to a
    4176              :    series of conditional moves.  Also check that we have more than one
    4177              :    set (other routines can handle a single set better than we would),
    4178              :    and fewer than PARAM_MAX_RTL_IF_CONVERSION_INSNS sets.  While going
    4179              :    through the insns store the sum of their potential costs in COST.  */
    4180              : 
    4181              : static bool
    4182      1074681 : bb_ok_for_noce_convert_multiple_sets (basic_block test_bb, unsigned *cost)
    4183              : {
    4184      1074681 :   rtx_insn *insn;
    4185      1074681 :   unsigned count = 0;
    4186      1074681 :   unsigned param = param_max_rtl_if_conversion_insns;
    4187      1074681 :   bool speed_p = optimize_bb_for_speed_p (test_bb);
    4188      1074681 :   unsigned potential_cost = 0;
    4189              : 
    4190      8698934 :   FOR_BB_INSNS (test_bb, insn)
    4191              :     {
    4192              :       /* Skip over notes etc.  */
    4193      8582718 :       if (!active_insn_p (insn))
    4194      6674911 :         continue;
    4195              : 
    4196              :       /* We only handle SET insns.  */
    4197      1907807 :       rtx set = single_set (insn);
    4198      1907807 :       if (set == NULL_RTX)
    4199              :         return false;
    4200              : 
    4201      1701757 :       rtx dest = SET_DEST (set);
    4202      1701757 :       rtx src = SET_SRC (set);
    4203              : 
    4204              :       /* Do not handle anything involving memory loads/stores since it might
    4205              :          violate data-race-freedom guarantees.  Make sure we can force SRC
    4206              :          to a register as that may be needed in try_emit_cmove_seq.  */
    4207      1497682 :       if (!REG_P (dest) || contains_mem_rtx_p (src)
    4208      2707311 :           || !noce_can_force_operand (src))
    4209       719928 :         return false;
    4210              : 
    4211              :       /* Destination and source must be appropriate.  */
    4212       981829 :       if (!noce_operand_ok (dest) || !noce_operand_ok (src))
    4213         5955 :         return false;
    4214              : 
    4215              :       /* We must be able to conditionally move in this mode.  */
    4216       975874 :       if (!can_conditionally_move_p (GET_MODE (dest)))
    4217              :         return false;
    4218              : 
    4219       949342 :       potential_cost += insn_cost (insn, speed_p);
    4220              : 
    4221       949342 :       count++;
    4222              :     }
    4223              : 
    4224       116216 :   *cost += potential_cost;
    4225              : 
    4226              :   /* If we would only put out one conditional move, the other strategies
    4227              :      this pass tries are better optimized and will be more appropriate.
    4228              :      Some targets want to strictly limit the number of conditional moves
    4229              :      that are emitted, they set this through PARAM, we need to respect
    4230              :      that.  */
    4231       116216 :   return count > 1 && count <= param;
    4232              : }
    4233              : 
    4234              : /* Compute average of two given costs weighted by relative probabilities
    4235              :    of respective basic blocks in an IF-THEN-ELSE.  E is the IF-THEN edge.
    4236              :    With P as the probability to take the IF-THEN branch, return
    4237              :    P * THEN_COST + (1 - P) * ELSE_COST.  */
    4238              : static unsigned
    4239       262638 : average_cost (unsigned then_cost, unsigned else_cost, edge e)
    4240              : {
    4241       262638 :   return else_cost + e->probability.apply ((signed) (then_cost - else_cost));
    4242              : }
    4243              : 
    4244              : /* Given a simple IF-THEN-JOIN or IF-THEN-ELSE-JOIN block, attempt to convert
    4245              :    it without using conditional execution.  Return TRUE if we were successful
    4246              :    at converting the block.  */
    4247              : 
    4248              : static bool
    4249      1878067 : noce_process_if_block (struct noce_if_info *if_info)
    4250              : {
    4251      1878067 :   basic_block test_bb = if_info->test_bb;    /* test block */
    4252      1878067 :   basic_block then_bb = if_info->then_bb;    /* THEN */
    4253      1878067 :   basic_block else_bb = if_info->else_bb;    /* ELSE or NULL */
    4254      1878067 :   basic_block join_bb = if_info->join_bb;    /* JOIN */
    4255      1878067 :   rtx_insn *jump = if_info->jump;
    4256      1878067 :   rtx cond = if_info->cond;
    4257      1878067 :   rtx_insn *insn_a, *insn_b;
    4258      1878067 :   rtx set_a, set_b;
    4259      1878067 :   rtx orig_x, x, a, b;
    4260              : 
    4261              :   /* We're looking for patterns of the form
    4262              : 
    4263              :      (1) if (...) x = a; else x = b;
    4264              :      (2) x = b; if (...) x = a;
    4265              :      (3) if (...) x = a;   // as if with an initial x = x.
    4266              :      (4) if (...) { x = a; y = b; z = c; }  // Like 3, for multiple SETS.
    4267              :      The later patterns require jumps to be more expensive.
    4268              :      For the if (...) x = a; else x = b; case we allow multiple insns
    4269              :      inside the then and else blocks as long as their only effect is
    4270              :      to calculate a value for x.
    4271              :      ??? For future expansion, further expand the "multiple X" rules.  */
    4272              : 
    4273              :   /* First look for multiple SETS.
    4274              :      The original costs already include costs for the jump insn as well
    4275              :      as for a CC comparison if there is any.
    4276              :      If a target re-uses the existing CC comparison we keep track of that
    4277              :      and add the costs before default noce_conversion_profitable_p.  */
    4278              : 
    4279      1878067 :   unsigned potential_cost = if_info->original_cost;
    4280      1878067 :   unsigned old_cost = if_info->original_cost;
    4281      1878067 :   if (!else_bb
    4282              :       && HAVE_conditional_move
    4283      1878067 :       && bb_ok_for_noce_convert_multiple_sets (then_bb, &potential_cost))
    4284              :     {
    4285              :       /* Temporarily set the original costs to what we estimated so
    4286              :          we can determine if the transformation is worth it.  */
    4287        31020 :       if_info->original_cost = potential_cost;
    4288        31020 :       if (noce_convert_multiple_sets (if_info))
    4289              :         {
    4290        25348 :           if (dump_file && if_info->transform_name)
    4291            1 :             fprintf (dump_file, "if-conversion succeeded through %s\n",
    4292              :                      if_info->transform_name);
    4293        25348 :           return true;
    4294              :         }
    4295              : 
    4296              :       /* Restore the original costs.  */
    4297         5672 :       if_info->original_cost = old_cost;
    4298              :     }
    4299              : 
    4300      1852719 :   bool speed_p = optimize_bb_for_speed_p (test_bb);
    4301      1852719 :   unsigned int then_cost = 0, else_cost = 0;
    4302      1852719 :   if (!bb_valid_for_noce_process_p (then_bb, cond, &then_cost,
    4303              :                                     &if_info->then_simple))
    4304              :     return false;
    4305              : 
    4306       499393 :   if (else_bb
    4307       499393 :       && !bb_valid_for_noce_process_p (else_bb, cond, &else_cost,
    4308              :                                        &if_info->else_simple))
    4309              :     return false;
    4310              : 
    4311       304736 :   if (speed_p)
    4312       262638 :     if_info->original_cost += average_cost (then_cost, else_cost,
    4313              :                                             find_edge (test_bb, then_bb));
    4314              :   else
    4315        42098 :     if_info->original_cost += then_cost + else_cost;
    4316              : 
    4317       304736 :   insn_a = last_active_insn (then_bb, false);
    4318       304736 :   set_a = single_set (insn_a);
    4319       304736 :   gcc_assert (set_a);
    4320              : 
    4321       304736 :   x = SET_DEST (set_a);
    4322       304736 :   a = SET_SRC (set_a);
    4323              : 
    4324              :   /* Look for the other potential set.  Make sure we've got equivalent
    4325              :      destinations.  */
    4326              :   /* ??? This is overconservative.  Storing to two different mems is
    4327              :      as easy as conditionally computing the address.  Storing to a
    4328              :      single mem merely requires a scratch memory to use as one of the
    4329              :      destination addresses; often the memory immediately below the
    4330              :      stack pointer is available for this.  */
    4331       304736 :   set_b = NULL_RTX;
    4332       304736 :   if (else_bb)
    4333              :     {
    4334        99715 :       insn_b = last_active_insn (else_bb, false);
    4335        99715 :       set_b = single_set (insn_b);
    4336        99715 :       gcc_assert (set_b);
    4337              : 
    4338        99715 :       if (!rtx_interchangeable_p (x, SET_DEST (set_b)))
    4339              :         return false;
    4340              :     }
    4341              :   else
    4342              :     {
    4343       205021 :       insn_b = if_info->cond_earliest;
    4344       545216 :       do
    4345       545216 :         insn_b = prev_nonnote_nondebug_insn (insn_b);
    4346              :       while (insn_b
    4347       542484 :              && (BLOCK_FOR_INSN (insn_b)
    4348       542484 :                  == BLOCK_FOR_INSN (if_info->cond_earliest))
    4349      1208858 :              && !modified_in_p (x, insn_b));
    4350              : 
    4351              :       /* We're going to be moving the evaluation of B down from above
    4352              :          COND_EARLIEST to JUMP.  Make sure the relevant data is still
    4353              :          intact.  */
    4354       205021 :       if (! insn_b
    4355       202289 :           || BLOCK_FOR_INSN (insn_b) != BLOCK_FOR_INSN (if_info->cond_earliest)
    4356       118426 :           || !NONJUMP_INSN_P (insn_b)
    4357       113181 :           || (set_b = single_set (insn_b)) == NULL_RTX
    4358       111738 :           || ! rtx_interchangeable_p (x, SET_DEST (set_b))
    4359        96864 :           || ! noce_operand_ok (SET_SRC (set_b))
    4360        94845 :           || reg_overlap_mentioned_p (x, SET_SRC (set_b))
    4361        92971 :           || modified_between_p (SET_SRC (set_b), insn_b, jump)
    4362              :           /* Avoid extending the lifetime of hard registers on small
    4363              :              register class machines.  */
    4364        90497 :           || (REG_P (SET_SRC (set_b))
    4365        26445 :               && HARD_REGISTER_P (SET_SRC (set_b))
    4366         3620 :               && targetm.small_register_classes_for_mode_p
    4367         3620 :                    (GET_MODE (SET_SRC (set_b))))
    4368              :           /* Likewise with X.  In particular this can happen when
    4369              :              noce_get_condition looks farther back in the instruction
    4370              :              stream than one might expect.  */
    4371        86877 :           || reg_overlap_mentioned_p (x, cond)
    4372        73932 :           || reg_overlap_mentioned_p (x, a)
    4373       273139 :           || modified_between_p (x, insn_b, jump))
    4374              :         {
    4375              :           insn_b = NULL;
    4376              :           set_b = NULL_RTX;
    4377              :         }
    4378              :     }
    4379              : 
    4380              :   /* If x has side effects then only the if-then-else form is safe to
    4381              :      convert.  But even in that case we would need to restore any notes
    4382              :      (such as REG_INC) at then end.  That can be tricky if
    4383              :      noce_emit_move_insn expands to more than one insn, so disable the
    4384              :      optimization entirely for now if there are side effects.  */
    4385       292234 :   if (side_effects_p (x))
    4386              :     return false;
    4387              : 
    4388       292234 :   b = (set_b ? SET_SRC (set_b) : x);
    4389              : 
    4390              :   /* Only operate on register destinations, and even then avoid extending
    4391              :      the lifetime of hard registers on small register class machines.  */
    4392       292234 :   orig_x = x;
    4393       292234 :   if_info->orig_x = orig_x;
    4394       292234 :   if (!REG_P (x)
    4395       292234 :       || (HARD_REGISTER_P (x)
    4396            2 :           && targetm.small_register_classes_for_mode_p (GET_MODE (x))))
    4397              :     {
    4398        67966 :       if (GET_MODE (x) == BLKmode)
    4399              :         return false;
    4400              : 
    4401        67731 :       if (GET_CODE (x) == ZERO_EXTRACT
    4402            3 :           && (!CONST_INT_P (XEXP (x, 1))
    4403            3 :               || !CONST_INT_P (XEXP (x, 2))))
    4404              :         return false;
    4405              : 
    4406        67731 :       x = gen_reg_rtx (GET_MODE (GET_CODE (x) == STRICT_LOW_PART
    4407              :                                  ? XEXP (x, 0) : x));
    4408              :     }
    4409              : 
    4410              :   /* Don't operate on sources that may trap or are volatile.  */
    4411       291999 :   if (! noce_operand_ok (a) || ! noce_operand_ok (b))
    4412            0 :     return false;
    4413              : 
    4414       337378 :  retry:
    4415              :   /* Set up the info block for our subroutines.  */
    4416       337378 :   if_info->insn_a = insn_a;
    4417       337378 :   if_info->insn_b = insn_b;
    4418       337378 :   if_info->x = x;
    4419       337378 :   if_info->a = a;
    4420       337378 :   if_info->b = b;
    4421              : 
    4422              :   /* Try optimizations in some approximation of a useful order.  */
    4423              :   /* ??? Should first look to see if X is live incoming at all.  If it
    4424              :      isn't, we don't need anything but an unconditional set.  */
    4425              : 
    4426              :   /* Look and see if A and B are really the same.  Avoid creating silly
    4427              :      cmove constructs that no one will fix up later.  */
    4428       337378 :   if (noce_simple_bbs (if_info)
    4429       314613 :       && rtx_interchangeable_p (a, b))
    4430              :     {
    4431              :       /* If we have an INSN_B, we don't have to create any new rtl.  Just
    4432              :          move the instruction that we already have.  If we don't have an
    4433              :          INSN_B, that means that A == X, and we've got a noop move.  In
    4434              :          that case don't do anything and let the code below delete INSN_A.  */
    4435          429 :       if (insn_b && else_bb)
    4436              :         {
    4437          418 :           rtx note;
    4438              : 
    4439          418 :           if (else_bb && insn_b == BB_END (else_bb))
    4440          233 :             BB_END (else_bb) = PREV_INSN (insn_b);
    4441          418 :           reorder_insns (insn_b, insn_b, PREV_INSN (jump));
    4442              : 
    4443              :           /* If there was a REG_EQUAL note, delete it since it may have been
    4444              :              true due to this insn being after a jump.  */
    4445          418 :           if ((note = find_reg_note (insn_b, REG_EQUAL, NULL_RTX)) != 0)
    4446            0 :             remove_note (insn_b, note);
    4447              : 
    4448          429 :           insn_b = NULL;
    4449              :         }
    4450              :       /* If we have "x = b; if (...) x = a;", and x has side-effects, then
    4451              :          x must be executed twice.  */
    4452           11 :       else if (insn_b && side_effects_p (orig_x))
    4453              :         return false;
    4454              : 
    4455          429 :       x = orig_x;
    4456          429 :       goto success;
    4457              :     }
    4458              : 
    4459       336949 :   if (!set_b && MEM_P (orig_x))
    4460              :     /* We want to avoid store speculation to avoid cases like
    4461              :          if (pthread_mutex_trylock(mutex))
    4462              :            ++global_variable;
    4463              :        Rather than go to much effort here, we rely on the SSA optimizers,
    4464              :        which do a good enough job these days.  */
    4465              :     return false;
    4466              : 
    4467       270754 :   if (noce_try_move (if_info))
    4468            0 :     goto success;
    4469       270754 :   if (noce_try_ifelse_collapse (if_info))
    4470        15619 :     goto success;
    4471       255135 :   if (noce_try_store_flag (if_info))
    4472        25904 :     goto success;
    4473       229231 :   if (noce_try_bitop (if_info))
    4474            0 :     goto success;
    4475       229231 :   if (noce_try_minmax (if_info))
    4476           53 :     goto success;
    4477       229178 :   if (noce_try_abs (if_info))
    4478           24 :     goto success;
    4479       229154 :   if (noce_try_inverse_constants (if_info))
    4480            0 :     goto success;
    4481       229154 :   if (!targetm.have_conditional_execution ()
    4482       229154 :       && noce_try_store_flag_constants (if_info))
    4483         2910 :     goto success;
    4484       226244 :   if (noce_try_sign_bit_splat (if_info))
    4485          188 :     goto success;
    4486       226056 :   if (HAVE_conditional_move
    4487       226056 :       && noce_try_cmove (if_info))
    4488        44329 :     goto success;
    4489       181727 :   if (! targetm.have_conditional_execution ())
    4490              :     {
    4491       181727 :       if (noce_try_addcc (if_info))
    4492         4772 :         goto success;
    4493       176955 :       if (noce_try_store_flag_mask (if_info))
    4494            2 :         goto success;
    4495       176953 :       if (HAVE_conditional_move
    4496       176953 :           && noce_try_cond_arith (if_info))
    4497         8424 :         goto success;
    4498       168529 :       if (HAVE_conditional_move
    4499       168529 :           && noce_try_cmove_arith (if_info))
    4500        25715 :         goto success;
    4501       142814 :       if (noce_try_sign_mask (if_info))
    4502            0 :         goto success;
    4503              :     }
    4504              : 
    4505       142814 :   if (!else_bb && set_b)
    4506              :     {
    4507        45379 :       insn_b = NULL;
    4508        45379 :       set_b = NULL_RTX;
    4509        45379 :       b = orig_x;
    4510        45379 :       goto retry;
    4511              :     }
    4512              : 
    4513              :   return false;
    4514              : 
    4515       128369 :  success:
    4516       128369 :   if (dump_file && if_info->transform_name)
    4517            5 :     fprintf (dump_file, "if-conversion succeeded through %s\n",
    4518              :              if_info->transform_name);
    4519              : 
    4520              :   /* If we used a temporary, fix it up now.  */
    4521       128369 :   if (orig_x != x)
    4522              :     {
    4523          644 :       rtx_insn *seq;
    4524              : 
    4525          644 :       start_sequence ();
    4526          644 :       noce_emit_move_insn (orig_x, x);
    4527          644 :       seq = get_insns ();
    4528          644 :       set_used_flags (orig_x);
    4529          644 :       unshare_all_rtl_in_chain (seq);
    4530          644 :       end_sequence ();
    4531              : 
    4532          644 :       emit_insn_before_setloc (seq, BB_END (test_bb), INSN_LOCATION (insn_a));
    4533              :     }
    4534              : 
    4535              :   /* The original THEN and ELSE blocks may now be removed.  The test block
    4536              :      must now jump to the join block.  If the test block and the join block
    4537              :      can be merged, do so.  */
    4538       128369 :   if (else_bb)
    4539              :     {
    4540        61132 :       delete_basic_block (else_bb);
    4541        61132 :       num_true_changes++;
    4542              :     }
    4543              :   else
    4544        67237 :     remove_edge (find_edge (test_bb, join_bb));
    4545              : 
    4546       128369 :   remove_edge (find_edge (then_bb, join_bb));
    4547       128369 :   redirect_edge_and_branch_force (single_succ_edge (test_bb), join_bb);
    4548       128369 :   delete_basic_block (then_bb);
    4549       128369 :   num_true_changes++;
    4550              : 
    4551       128369 :   if (can_merge_blocks_p (test_bb, join_bb))
    4552              :     {
    4553        99449 :       merge_blocks (test_bb, join_bb);
    4554        99449 :       num_true_changes++;
    4555              :     }
    4556              : 
    4557       128369 :   num_updated_if_blocks++;
    4558       128369 :   return true;
    4559              : }
    4560              : 
    4561              : /* Check whether a block is suitable for conditional move conversion.
    4562              :    Every insn must be a simple set of a register to a constant or a
    4563              :    register.  For each assignment, store the value in the pointer map
    4564              :    VALS, keyed indexed by register pointer, then store the register
    4565              :    pointer in REGS.  COND is the condition we will test.  */
    4566              : 
    4567              : static bool
    4568      1763475 : check_cond_move_block (basic_block bb,
    4569              :                        hash_map<rtx, rtx> *vals,
    4570              :                        vec<rtx> *regs,
    4571              :                        rtx cond)
    4572              : {
    4573      1763475 :   rtx_insn *insn;
    4574      1763475 :   rtx cc = cc_in_cond (cond);
    4575              : 
    4576              :    /* We can only handle simple jumps at the end of the basic block.
    4577              :       It is almost impossible to update the CFG otherwise.  */
    4578      1763475 :   insn = BB_END (bb);
    4579      1763475 :   if (JUMP_P (insn) && !onlyjump_p (insn))
    4580              :     return false;
    4581              : 
    4582     10070895 :   FOR_BB_INSNS (bb, insn)
    4583              :     {
    4584      9989296 :       rtx set, dest, src;
    4585              : 
    4586      9989296 :       if (!NONDEBUG_INSN_P (insn) || JUMP_P (insn))
    4587      8115718 :         continue;
    4588      1873578 :       set = single_set (insn);
    4589      1873578 :       if (!set)
    4590      1681823 :         return false;
    4591              : 
    4592      1800376 :       dest = SET_DEST (set);
    4593      1800376 :       src = SET_SRC (set);
    4594      1800376 :       if (!REG_P (dest)
    4595      1800376 :           || (HARD_REGISTER_P (dest)
    4596       272209 :               && targetm.small_register_classes_for_mode_p (GET_MODE (dest))))
    4597       651925 :         return false;
    4598              : 
    4599      1148451 :       if (!CONSTANT_P (src) && !register_operand (src, VOIDmode))
    4600              :         return false;
    4601              : 
    4602       214897 :       if (side_effects_p (src) || side_effects_p (dest))
    4603            0 :         return false;
    4604              : 
    4605       214897 :       if (may_trap_p (src) || may_trap_p (dest))
    4606            0 :         return false;
    4607              : 
    4608              :       /* Don't try to handle this if the source register was
    4609              :          modified earlier in the block.  */
    4610       214897 :       if ((REG_P (src)
    4611        49277 :            && vals->get (src))
    4612       263890 :           || (GET_CODE (src) == SUBREG && REG_P (SUBREG_REG (src))
    4613         5920 :               && vals->get (SUBREG_REG (src))))
    4614          335 :         return false;
    4615              : 
    4616              :       /* Don't try to handle this if the destination register was
    4617              :          modified earlier in the block.  */
    4618       214562 :       if (vals->get (dest))
    4619              :         return false;
    4620              : 
    4621              :       /* Don't try to handle this if the condition uses the
    4622              :          destination register.  */
    4623       214562 :       if (reg_overlap_mentioned_p (dest, cond))
    4624              :         return false;
    4625              : 
    4626              :       /* Don't try to handle this if the source register is modified
    4627              :          later in the block.  */
    4628       194800 :       if (!CONSTANT_P (src)
    4629       194800 :           && modified_between_p (src, insn, NEXT_INSN (BB_END (bb))))
    4630              :         return false;
    4631              : 
    4632              :       /* Skip it if the instruction to be moved might clobber CC.  */
    4633       191755 :       if (cc && set_of (cc, insn))
    4634              :         return false;
    4635              : 
    4636       191755 :       vals->put (dest, src);
    4637              : 
    4638       191755 :       regs->safe_push (dest);
    4639              :     }
    4640              : 
    4641              :   return true;
    4642              : }
    4643              : 
    4644              : /* Given a basic block BB suitable for conditional move conversion,
    4645              :    a condition COND, and pointer maps THEN_VALS and ELSE_VALS containing
    4646              :    the register values depending on COND, emit the insns in the block as
    4647              :    conditional moves.  If ELSE_BLOCK is true, THEN_BB was already
    4648              :    processed.  The caller has started a sequence for the conversion.
    4649              :    Return true if successful, false if something goes wrong.  */
    4650              : 
    4651              : static bool
    4652        57629 : cond_move_convert_if_block (struct noce_if_info *if_infop,
    4653              :                             basic_block bb, rtx cond,
    4654              :                             hash_map<rtx, rtx> *then_vals,
    4655              :                             hash_map<rtx, rtx> *else_vals,
    4656              :                             bool else_block_p)
    4657              : {
    4658        57629 :   enum rtx_code code;
    4659        57629 :   rtx_insn *insn;
    4660        57629 :   rtx cond_arg0, cond_arg1;
    4661              : 
    4662        57629 :   code = GET_CODE (cond);
    4663        57629 :   cond_arg0 = XEXP (cond, 0);
    4664        57629 :   cond_arg1 = XEXP (cond, 1);
    4665              : 
    4666       242591 :   FOR_BB_INSNS (bb, insn)
    4667              :     {
    4668       200083 :       rtx set, target, dest, t, e;
    4669              : 
    4670              :       /* ??? Maybe emit conditional debug insn?  */
    4671       200083 :       if (!NONDEBUG_INSN_P (insn) || JUMP_P (insn))
    4672       129919 :         continue;
    4673       113700 :       set = single_set (insn);
    4674       113700 :       gcc_assert (set && REG_P (SET_DEST (set)));
    4675              : 
    4676       113700 :       dest = SET_DEST (set);
    4677              : 
    4678       113700 :       rtx *then_slot = then_vals->get (dest);
    4679       113700 :       rtx *else_slot = else_vals->get (dest);
    4680       113700 :       t = then_slot ? *then_slot : NULL_RTX;
    4681       113700 :       e = else_slot ? *else_slot : NULL_RTX;
    4682              : 
    4683       113700 :       if (else_block_p)
    4684              :         {
    4685              :           /* If this register was set in the then block, we already
    4686              :              handled this case there.  */
    4687        46017 :           if (t)
    4688        43536 :             continue;
    4689         2481 :           t = dest;
    4690         2481 :           gcc_assert (e);
    4691              :         }
    4692              :       else
    4693              :         {
    4694        67683 :           gcc_assert (t);
    4695        67683 :           if (!e)
    4696        23470 :             e = dest;
    4697              :         }
    4698              : 
    4699        70164 :       if (if_infop->cond_inverted)
    4700            0 :         std::swap (t, e);
    4701              : 
    4702        70164 :       target = noce_emit_cmove (if_infop, dest, code, cond_arg0, cond_arg1,
    4703              :                                 t, e);
    4704        70164 :       if (!target)
    4705        15121 :         return false;
    4706              : 
    4707        55043 :       if (target != dest)
    4708            0 :         noce_emit_move_insn (dest, target);
    4709              :     }
    4710              : 
    4711              :   return true;
    4712              : }
    4713              : 
    4714              : /* Given a simple IF-THEN-JOIN or IF-THEN-ELSE-JOIN block, attempt to convert
    4715              :    it using only conditional moves.  Return TRUE if we were successful at
    4716              :    converting the block.  */
    4717              : 
    4718              : static bool
    4719      1724350 : cond_move_process_if_block (struct noce_if_info *if_info)
    4720              : {
    4721      1724350 :   basic_block test_bb = if_info->test_bb;
    4722      1724350 :   basic_block then_bb = if_info->then_bb;
    4723      1724350 :   basic_block else_bb = if_info->else_bb;
    4724      1724350 :   basic_block join_bb = if_info->join_bb;
    4725      1724350 :   rtx_insn *jump = if_info->jump;
    4726      1724350 :   rtx cond = if_info->cond;
    4727      1724350 :   rtx_insn *seq, *loc_insn;
    4728      1724350 :   int c;
    4729      1724350 :   vec<rtx> then_regs = vNULL;
    4730      1724350 :   vec<rtx> else_regs = vNULL;
    4731      1724350 :   bool success_p = false;
    4732      1724350 :   int limit = param_max_rtl_if_conversion_insns;
    4733              : 
    4734              :   /* Build a mapping for each block to the value used for each
    4735              :      register.  */
    4736      1724350 :   hash_map<rtx, rtx> then_vals;
    4737      1724350 :   hash_map<rtx, rtx> else_vals;
    4738              : 
    4739              :   /* Make sure the blocks are suitable.  */
    4740      1724350 :   if (!check_cond_move_block (then_bb, &then_vals, &then_regs, cond)
    4741      1724350 :       || (else_bb
    4742        39125 :           && !check_cond_move_block (else_bb, &else_vals, &else_regs, cond)))
    4743      1681876 :     goto done;
    4744              : 
    4745              :   /* Make sure the blocks can be used together.  If the same register
    4746              :      is set in both blocks, and is not set to a constant in both
    4747              :      cases, then both blocks must set it to the same register.  We
    4748              :      have already verified that if it is set to a register, that the
    4749              :      source register does not change after the assignment.  Also count
    4750              :      the number of registers set in only one of the blocks.  */
    4751        42474 :   c = 0;
    4752       196224 :   for (rtx reg : then_regs)
    4753              :     {
    4754        71678 :       rtx *then_slot = then_vals.get (reg);
    4755        71678 :       rtx *else_slot = else_vals.get (reg);
    4756              : 
    4757        71678 :       gcc_checking_assert (then_slot);
    4758        71678 :       if (!else_slot)
    4759        24189 :         ++c;
    4760              :       else
    4761              :         {
    4762        47489 :           rtx then_val = *then_slot;
    4763        47489 :           rtx else_val = *else_slot;
    4764         4159 :           if (!CONSTANT_P (then_val) && !CONSTANT_P (else_val)
    4765        50706 :               && !rtx_equal_p (then_val, else_val))
    4766         2632 :             goto done;
    4767              :         }
    4768              :     }
    4769              : 
    4770              :   /* Finish off c for MAX_CONDITIONAL_EXECUTE.  */
    4771       124272 :   for (rtx reg : else_regs)
    4772              :     {
    4773        47336 :       gcc_checking_assert (else_vals.get (reg));
    4774        47336 :       if (!then_vals.get (reg))
    4775         2638 :         ++c;
    4776              :     }
    4777              : 
    4778              :   /* Make sure it is reasonable to convert this block.  What matters
    4779              :      is the number of assignments currently made in only one of the
    4780              :      branches, since if we convert we are going to always execute
    4781              :      them.  */
    4782        39842 :   if (c > MAX_CONDITIONAL_EXECUTE
    4783        39842 :       || c > limit)
    4784           38 :     goto done;
    4785              : 
    4786              :   /* Try to emit the conditional moves.  First do the then block,
    4787              :      then do anything left in the else blocks.  */
    4788        39804 :   start_sequence ();
    4789        39804 :   if (!cond_move_convert_if_block (if_info, then_bb, cond,
    4790              :                                    &then_vals, &else_vals, false)
    4791        39804 :       || (else_bb
    4792        17825 :           && !cond_move_convert_if_block (if_info, else_bb, cond,
    4793              :                                           &then_vals, &else_vals, true)))
    4794              :     {
    4795        15121 :       end_sequence ();
    4796        15121 :       goto done;
    4797              :     }
    4798        24683 :   seq = end_ifcvt_sequence (if_info);
    4799        24683 :   if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
    4800        20627 :     goto done;
    4801              : 
    4802         4056 :   loc_insn = first_active_insn (then_bb);
    4803         4056 :   if (!loc_insn)
    4804              :     {
    4805            0 :       loc_insn = first_active_insn (else_bb);
    4806            0 :       gcc_assert (loc_insn);
    4807              :     }
    4808         4056 :   emit_insn_before_setloc (seq, jump, INSN_LOCATION (loc_insn));
    4809              : 
    4810         4056 :   if (else_bb)
    4811              :     {
    4812         4056 :       delete_basic_block (else_bb);
    4813         4056 :       num_true_changes++;
    4814              :     }
    4815              :   else
    4816            0 :     remove_edge (find_edge (test_bb, join_bb));
    4817              : 
    4818         4056 :   remove_edge (find_edge (then_bb, join_bb));
    4819         4056 :   redirect_edge_and_branch_force (single_succ_edge (test_bb), join_bb);
    4820         4056 :   delete_basic_block (then_bb);
    4821         4056 :   num_true_changes++;
    4822              : 
    4823         4056 :   if (can_merge_blocks_p (test_bb, join_bb))
    4824              :     {
    4825          728 :       merge_blocks (test_bb, join_bb);
    4826          728 :       num_true_changes++;
    4827              :     }
    4828              : 
    4829         4056 :   num_updated_if_blocks++;
    4830         4056 :   success_p = true;
    4831              : 
    4832      1724350 : done:
    4833      1724350 :   then_regs.release ();
    4834      1724350 :   else_regs.release ();
    4835      1724350 :   return success_p;
    4836      1724350 : }
    4837              : 
    4838              : 
    4839              : /* Determine if a given basic block heads a simple IF-THEN-JOIN or an
    4840              :    IF-THEN-ELSE-JOIN block.
    4841              : 
    4842              :    If so, we'll try to convert the insns to not require the branch,
    4843              :    using only transformations that do not require conditional execution.
    4844              : 
    4845              :    Return TRUE if we were successful at converting the block.  */
    4846              : 
    4847              : static bool
    4848      9752668 : noce_find_if_block (basic_block test_bb, edge then_edge, edge else_edge,
    4849              :                     int pass)
    4850              : {
    4851      9752668 :   basic_block then_bb, else_bb, join_bb;
    4852      9752668 :   bool then_else_reversed = false;
    4853      9752668 :   rtx_insn *jump;
    4854      9752668 :   rtx_insn *cond_earliest;
    4855      9752668 :   struct noce_if_info if_info;
    4856      9752668 :   bool speed_p = optimize_bb_for_speed_p (test_bb);
    4857              : 
    4858              :   /* We only ever should get here before reload.  */
    4859      9752668 :   gcc_assert (!reload_completed);
    4860              : 
    4861              :   /* Recognize an IF-THEN-ELSE-JOIN block.  */
    4862      9752668 :   if (single_pred_p (then_edge->dest)
    4863      8024713 :       && single_succ_p (then_edge->dest)
    4864      3585535 :       && single_pred_p (else_edge->dest)
    4865     10037454 :       && single_succ_p (else_edge->dest)
    4866     10906903 :       && single_succ (then_edge->dest) == single_succ (else_edge->dest))
    4867              :     {
    4868              :       then_bb = then_edge->dest;
    4869              :       else_bb = else_edge->dest;
    4870              :       join_bb = single_succ (then_bb);
    4871              :     }
    4872              :   /* Recognize an IF-THEN-JOIN block.  */
    4873      8883219 :   else if (single_pred_p (then_edge->dest)
    4874     10650988 :            && single_succ_p (then_edge->dest)
    4875     11599305 :            && single_succ (then_edge->dest) == else_edge->dest)
    4876              :     {
    4877              :       then_bb = then_edge->dest;
    4878              :       else_bb = NULL_BLOCK;
    4879              :       join_bb = else_edge->dest;
    4880              :     }
    4881              :   /* Recognize an IF-ELSE-JOIN block.  We can have those because the order
    4882              :      of basic blocks in cfglayout mode does not matter, so the fallthrough
    4883              :      edge can go to any basic block (and not just to bb->next_bb, like in
    4884              :      cfgrtl mode).  */
    4885     17529797 :   else if (single_pred_p (else_edge->dest)
    4886     10925767 :            && single_succ_p (else_edge->dest)
    4887      9265774 :            && single_succ (else_edge->dest) == then_edge->dest)
    4888              :     {
    4889              :       /* The noce transformations do not apply to IF-ELSE-JOIN blocks.
    4890              :          To make this work, we have to invert the THEN and ELSE blocks
    4891              :          and reverse the jump condition.  */
    4892              :       then_bb = else_edge->dest;
    4893              :       else_bb = NULL_BLOCK;
    4894              :       join_bb = single_succ (then_bb);
    4895              :       then_else_reversed = true;
    4896              :     }
    4897              :   else
    4898              :     /* Not a form we can handle.  */
    4899              :     return false;
    4900              : 
    4901              :   /* The edges of the THEN and ELSE blocks cannot have complex edges.  */
    4902      1947661 :   if (single_succ_edge (then_bb)->flags & EDGE_COMPLEX)
    4903              :     return false;
    4904      1892246 :   if (else_bb
    4905      1892246 :       && single_succ_edge (else_bb)->flags & EDGE_COMPLEX)
    4906              :     return false;
    4907              : 
    4908      1881931 :   num_possible_if_blocks++;
    4909              : 
    4910      1881931 :   if (dump_file)
    4911              :     {
    4912           90 :       fprintf (dump_file,
    4913              :                "\nIF-THEN%s-JOIN block found, pass %d, test %d, then %d",
    4914              :                (else_bb) ? "-ELSE" : "",
    4915              :                pass, test_bb->index, then_bb->index);
    4916              : 
    4917           53 :       if (else_bb)
    4918           16 :         fprintf (dump_file, ", else %d", else_bb->index);
    4919              : 
    4920           53 :       fprintf (dump_file, ", join %d\n", join_bb->index);
    4921              :     }
    4922              : 
    4923              :   /* If the conditional jump is more than just a conditional
    4924              :      jump, then we cannot do if-conversion on this block.  */
    4925      1881931 :   jump = BB_END (test_bb);
    4926      1881931 :   if (! onlyjump_p (jump))
    4927              :     return false;
    4928              : 
    4929              :   /* Initialize an IF_INFO struct to pass around.  */
    4930      1881698 :   memset (&if_info, 0, sizeof if_info);
    4931      1881698 :   if_info.test_bb = test_bb;
    4932      1881698 :   if_info.then_bb = then_bb;
    4933      1881698 :   if_info.else_bb = else_bb;
    4934      1881698 :   if_info.join_bb = join_bb;
    4935      1881698 :   if_info.cond = noce_get_condition (jump, &cond_earliest,
    4936              :                                      then_else_reversed);
    4937      1881698 :   rtx_insn *rev_cond_earliest;
    4938      3763396 :   if_info.rev_cond = noce_get_condition (jump, &rev_cond_earliest,
    4939      1881698 :                                          !then_else_reversed);
    4940      1881698 :   if (!if_info.cond && !if_info.rev_cond)
    4941              :     return false;
    4942      1878067 :   if (!if_info.cond)
    4943              :     {
    4944            0 :       std::swap (if_info.cond, if_info.rev_cond);
    4945            0 :       std::swap (cond_earliest, rev_cond_earliest);
    4946            0 :       if_info.cond_inverted = true;
    4947              :     }
    4948              :   /* We must be comparing objects whose modes imply the size.  */
    4949      1878067 :   if (GET_MODE (XEXP (if_info.cond, 0)) == BLKmode)
    4950              :     return false;
    4951      1878067 :   gcc_assert (if_info.rev_cond == NULL_RTX
    4952              :               || rev_cond_earliest == cond_earliest);
    4953      1878067 :   if_info.cond_earliest = cond_earliest;
    4954      1878067 :   if_info.jump = jump;
    4955      1878067 :   if_info.then_else_reversed = then_else_reversed;
    4956      1878067 :   if_info.speed_p = speed_p;
    4957      1878067 :   if_info.max_seq_cost
    4958      1878067 :     = targetm.max_noce_ifcvt_seq_cost (then_edge);
    4959              :   /* We'll add in the cost of THEN_BB and ELSE_BB later, when we check
    4960              :      that they are valid to transform.  We can't easily get back to the insn
    4961              :      for COND (and it may not exist if we had to canonicalize to get COND).
    4962              :      It is assumed that the costs of a jump insn are dependent on the
    4963              :      branch costs.  */
    4964      1878067 :   if_info.original_cost += insn_cost (if_info.jump, if_info.speed_p);
    4965              : 
    4966              :   /* Do the real work.  */
    4967              : 
    4968              :   /* ??? noce_process_if_block has not yet been updated to handle
    4969              :      inverted conditions.  */
    4970      1878067 :   if (!if_info.cond_inverted && noce_process_if_block (&if_info))
    4971              :     return true;
    4972              : 
    4973      1724350 :   if (HAVE_conditional_move
    4974      1724350 :       && cond_move_process_if_block (&if_info))
    4975              :     return true;
    4976              : 
    4977              :   return false;
    4978              : }
    4979              : 
    4980              : 
    4981              : /* Merge the blocks and mark for local life update.  */
    4982              : 
    4983              : static void
    4984            0 : merge_if_block (struct ce_if_block * ce_info)
    4985              : {
    4986            0 :   basic_block test_bb = ce_info->test_bb;    /* last test block */
    4987            0 :   basic_block then_bb = ce_info->then_bb;    /* THEN */
    4988            0 :   basic_block else_bb = ce_info->else_bb;    /* ELSE or NULL */
    4989            0 :   basic_block join_bb = ce_info->join_bb;    /* join block */
    4990            0 :   basic_block combo_bb;
    4991              : 
    4992              :   /* All block merging is done into the lower block numbers.  */
    4993              : 
    4994            0 :   combo_bb = test_bb;
    4995            0 :   df_set_bb_dirty (test_bb);
    4996              : 
    4997              :   /* Merge any basic blocks to handle && and || subtests.  Each of
    4998              :      the blocks are on the fallthru path from the predecessor block.  */
    4999            0 :   if (ce_info->num_multiple_test_blocks > 0)
    5000              :     {
    5001            0 :       basic_block bb = test_bb;
    5002            0 :       basic_block last_test_bb = ce_info->last_test_bb;
    5003            0 :       basic_block fallthru = block_fallthru (bb);
    5004              : 
    5005            0 :       do
    5006              :         {
    5007            0 :           bb = fallthru;
    5008            0 :           fallthru = block_fallthru (bb);
    5009            0 :           merge_blocks (combo_bb, bb);
    5010            0 :           num_true_changes++;
    5011              :         }
    5012            0 :       while (bb != last_test_bb);
    5013              :     }
    5014              : 
    5015              :   /* Merge TEST block into THEN block.  Normally the THEN block won't have a
    5016              :      label, but it might if there were || tests.  That label's count should be
    5017              :      zero, and it normally should be removed.  */
    5018              : 
    5019            0 :   if (then_bb)
    5020              :     {
    5021              :       /* If THEN_BB has no successors, then there's a BARRIER after it.
    5022              :          If COMBO_BB has more than one successor (THEN_BB), then that BARRIER
    5023              :          is no longer needed, and in fact it is incorrect to leave it in
    5024              :          the insn stream.  */
    5025            0 :       if (EDGE_COUNT (then_bb->succs) == 0
    5026            0 :           && EDGE_COUNT (combo_bb->succs) > 1)
    5027              :         {
    5028            0 :           rtx_insn *end = NEXT_INSN (BB_END (then_bb));
    5029            0 :           while (end && NOTE_P (end) && !NOTE_INSN_BASIC_BLOCK_P (end))
    5030            0 :             end = NEXT_INSN (end);
    5031              : 
    5032            0 :           if (end && BARRIER_P (end))
    5033            0 :             delete_insn (end);
    5034              :         }
    5035            0 :       merge_blocks (combo_bb, then_bb);
    5036            0 :       num_true_changes++;
    5037              :     }
    5038              : 
    5039              :   /* The ELSE block, if it existed, had a label.  That label count
    5040              :      will almost always be zero, but odd things can happen when labels
    5041              :      get their addresses taken.  */
    5042            0 :   if (else_bb)
    5043              :     {
    5044              :       /* If ELSE_BB has no successors, then there's a BARRIER after it.
    5045              :          If COMBO_BB has more than one successor (ELSE_BB), then that BARRIER
    5046              :          is no longer needed, and in fact it is incorrect to leave it in
    5047              :          the insn stream.  */
    5048            0 :       if (EDGE_COUNT (else_bb->succs) == 0
    5049            0 :           && EDGE_COUNT (combo_bb->succs) > 1)
    5050              :         {
    5051            0 :           rtx_insn *end = NEXT_INSN (BB_END (else_bb));
    5052            0 :           while (end && NOTE_P (end) && !NOTE_INSN_BASIC_BLOCK_P (end))
    5053            0 :             end = NEXT_INSN (end);
    5054              : 
    5055            0 :           if (end && BARRIER_P (end))
    5056            0 :             delete_insn (end);
    5057              :         }
    5058            0 :       merge_blocks (combo_bb, else_bb);
    5059            0 :       num_true_changes++;
    5060              :     }
    5061              : 
    5062              :   /* If there was no join block reported, that means it was not adjacent
    5063              :      to the others, and so we cannot merge them.  */
    5064              : 
    5065            0 :   if (! join_bb)
    5066              :     {
    5067            0 :       rtx_insn *last = BB_END (combo_bb);
    5068              : 
    5069              :       /* The outgoing edge for the current COMBO block should already
    5070              :          be correct.  Verify this.  */
    5071            0 :       if (EDGE_COUNT (combo_bb->succs) == 0)
    5072            0 :         gcc_assert (find_reg_note (last, REG_NORETURN, NULL)
    5073              :                     || (NONJUMP_INSN_P (last)
    5074              :                         && GET_CODE (PATTERN (last)) == TRAP_IF
    5075              :                         && (TRAP_CONDITION (PATTERN (last))
    5076              :                             == const_true_rtx)));
    5077              : 
    5078              :       else
    5079              :       /* There should still be something at the end of the THEN or ELSE
    5080              :          blocks taking us to our final destination.  */
    5081            0 :         gcc_assert (JUMP_P (last)
    5082              :                     || (EDGE_SUCC (combo_bb, 0)->dest
    5083              :                         == EXIT_BLOCK_PTR_FOR_FN (cfun)
    5084              :                         && CALL_P (last)
    5085              :                         && SIBLING_CALL_P (last))
    5086              :                     || ((EDGE_SUCC (combo_bb, 0)->flags & EDGE_EH)
    5087              :                         && can_throw_internal (last)));
    5088              :     }
    5089              : 
    5090              :   /* The JOIN block may have had quite a number of other predecessors too.
    5091              :      Since we've already merged the TEST, THEN and ELSE blocks, we should
    5092              :      have only one remaining edge from our if-then-else diamond.  If there
    5093              :      is more than one remaining edge, it must come from elsewhere.  There
    5094              :      may be zero incoming edges if the THEN block didn't actually join
    5095              :      back up (as with a call to a non-return function).  */
    5096            0 :   else if (EDGE_COUNT (join_bb->preds) < 2
    5097            0 :            && join_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
    5098              :     {
    5099              :       /* We can merge the JOIN cleanly and update the dataflow try
    5100              :          again on this pass.*/
    5101            0 :       merge_blocks (combo_bb, join_bb);
    5102            0 :       num_true_changes++;
    5103              :     }
    5104              :   else
    5105              :     {
    5106              :       /* We cannot merge the JOIN.  */
    5107              : 
    5108              :       /* The outgoing edge for the current COMBO block should already
    5109              :          be correct.  Verify this.  */
    5110            0 :       gcc_assert (single_succ_p (combo_bb)
    5111              :                   && single_succ (combo_bb) == join_bb);
    5112              : 
    5113              :       /* Remove the jump and cruft from the end of the COMBO block.  */
    5114            0 :       if (join_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
    5115            0 :         tidy_fallthru_edge (single_succ_edge (combo_bb));
    5116              :     }
    5117              : 
    5118            0 :   num_updated_if_blocks++;
    5119            0 : }
    5120              : 
    5121              : /* Find a block ending in a simple IF condition and try to transform it
    5122              :    in some way.  When converting a multi-block condition, put the new code
    5123              :    in the first such block and delete the rest.  Return a pointer to this
    5124              :    first block if some transformation was done.  Return NULL otherwise.  */
    5125              : 
    5126              : static basic_block
    5127     39392860 : find_if_header (basic_block test_bb, int pass)
    5128              : {
    5129     39392860 :   ce_if_block ce_info;
    5130     39392860 :   edge then_edge;
    5131     39392860 :   edge else_edge;
    5132              : 
    5133              :   /* The kind of block we're looking for has exactly two successors.  */
    5134     59409793 :   if (EDGE_COUNT (test_bb->succs) != 2)
    5135              :     return NULL;
    5136              : 
    5137     20327625 :   then_edge = EDGE_SUCC (test_bb, 0);
    5138     20327625 :   else_edge = EDGE_SUCC (test_bb, 1);
    5139              : 
    5140     20327625 :   if (df_get_bb_dirty (then_edge->dest))
    5141              :     return NULL;
    5142     20308636 :   if (df_get_bb_dirty (else_edge->dest))
    5143              :     return NULL;
    5144              : 
    5145              :   /* Neither edge should be abnormal.  */
    5146     20274092 :   if ((then_edge->flags & EDGE_COMPLEX)
    5147     18547078 :       || (else_edge->flags & EDGE_COMPLEX))
    5148              :     return NULL;
    5149              : 
    5150              :   /* Nor exit the loop.  */
    5151     18169374 :   if ((then_edge->flags & EDGE_LOOP_EXIT)
    5152     16721926 :       || (else_edge->flags & EDGE_LOOP_EXIT))
    5153              :     return NULL;
    5154              : 
    5155              :   /* The THEN edge is canonically the one that falls through.  */
    5156     14396454 :   if (then_edge->flags & EDGE_FALLTHRU)
    5157              :     ;
    5158      6988000 :   else if (else_edge->flags & EDGE_FALLTHRU)
    5159              :     std::swap (then_edge, else_edge);
    5160              :   else
    5161              :     /* Otherwise this must be a multiway branch of some sort.  */
    5162              :     return NULL;
    5163              : 
    5164     14396281 :   memset (&ce_info, 0, sizeof (ce_info));
    5165     14396281 :   ce_info.test_bb = test_bb;
    5166     14396281 :   ce_info.then_bb = then_edge->dest;
    5167     14396281 :   ce_info.else_bb = else_edge->dest;
    5168     14396281 :   ce_info.pass = pass;
    5169              : 
    5170              : #ifdef IFCVT_MACHDEP_INIT
    5171              :   IFCVT_MACHDEP_INIT (&ce_info);
    5172              : #endif
    5173              : 
    5174     14396281 :   if (!reload_completed
    5175     14396281 :       && noce_find_if_block (test_bb, then_edge, else_edge, pass))
    5176       157773 :     goto success;
    5177              : 
    5178     14238508 :   if (reload_completed
    5179      4643613 :       && targetm.have_conditional_execution ()
    5180     14238508 :       && cond_exec_find_if_block (&ce_info))
    5181            0 :     goto success;
    5182              : 
    5183     14238508 :   if (targetm.have_trap ()
    5184     14238508 :       && optab_handler (ctrap_optab, word_mode) != CODE_FOR_nothing
    5185     14238508 :       && find_cond_trap (test_bb, then_edge, else_edge))
    5186            0 :     goto success;
    5187              : 
    5188     14238508 :   if (dom_info_state (CDI_POST_DOMINATORS) >= DOM_NO_FAST_QUERY
    5189     14238508 :       && (reload_completed || !targetm.have_conditional_execution ()))
    5190              :     {
    5191     14238508 :       if (find_if_case_1 (test_bb, then_edge, else_edge))
    5192        22938 :         goto success;
    5193     14215570 :       if (find_if_case_2 (test_bb, then_edge, else_edge))
    5194       129981 :         goto success;
    5195              :     }
    5196              : 
    5197              :   return NULL;
    5198              : 
    5199       310692 :  success:
    5200       310692 :   if (dump_file)
    5201           19 :     fprintf (dump_file, "Conversion succeeded on pass %d.\n", pass);
    5202              :   /* Set this so we continue looking.  */
    5203       310692 :   cond_exec_changed_p = true;
    5204       310692 :   return ce_info.test_bb;
    5205              : }
    5206              : 
    5207              : /* Return true if a block has two edges, one of which falls through to the next
    5208              :    block, and the other jumps to a specific block, so that we can tell if the
    5209              :    block is part of an && test or an || test.  Returns either -1 or the number
    5210              :    of non-note, non-jump, non-USE/CLOBBER insns in the block.  */
    5211              : 
    5212              : static int
    5213            0 : block_jumps_and_fallthru (basic_block cur_bb, basic_block target_bb)
    5214              : {
    5215            0 :   edge cur_edge;
    5216            0 :   bool fallthru_p = false;
    5217            0 :   bool jump_p = false;
    5218            0 :   rtx_insn *insn;
    5219            0 :   rtx_insn *end;
    5220            0 :   int n_insns = 0;
    5221            0 :   edge_iterator ei;
    5222              : 
    5223            0 :   if (!cur_bb || !target_bb)
    5224              :     return -1;
    5225              : 
    5226              :   /* If no edges, obviously it doesn't jump or fallthru.  */
    5227            0 :   if (EDGE_COUNT (cur_bb->succs) == 0)
    5228              :     return 0;
    5229              : 
    5230            0 :   FOR_EACH_EDGE (cur_edge, ei, cur_bb->succs)
    5231              :     {
    5232            0 :       if (cur_edge->flags & EDGE_COMPLEX)
    5233              :         /* Anything complex isn't what we want.  */
    5234              :         return -1;
    5235              : 
    5236            0 :       else if (cur_edge->flags & EDGE_FALLTHRU)
    5237              :         fallthru_p = true;
    5238              : 
    5239            0 :       else if (cur_edge->dest == target_bb)
    5240              :         jump_p = true;
    5241              : 
    5242              :       else
    5243              :         return -1;
    5244              :     }
    5245              : 
    5246            0 :   if ((jump_p & fallthru_p) == 0)
    5247              :     return -1;
    5248              : 
    5249              :   /* Don't allow calls in the block, since this is used to group && and ||
    5250              :      together for conditional execution support.  ??? we should support
    5251              :      conditional execution support across calls for IA-64 some day, but
    5252              :      for now it makes the code simpler.  */
    5253            0 :   end = BB_END (cur_bb);
    5254            0 :   insn = BB_HEAD (cur_bb);
    5255              : 
    5256            0 :   while (insn != NULL_RTX)
    5257              :     {
    5258            0 :       if (CALL_P (insn))
    5259              :         return -1;
    5260              : 
    5261            0 :       if (INSN_P (insn)
    5262            0 :           && !JUMP_P (insn)
    5263            0 :           && !DEBUG_INSN_P (insn)
    5264            0 :           && GET_CODE (PATTERN (insn)) != USE
    5265            0 :           && GET_CODE (PATTERN (insn)) != CLOBBER)
    5266            0 :         n_insns++;
    5267              : 
    5268            0 :       if (insn == end)
    5269              :         break;
    5270              : 
    5271            0 :       insn = NEXT_INSN (insn);
    5272              :     }
    5273              : 
    5274              :   return n_insns;
    5275              : }
    5276              : 
    5277              : /* Determine if a given basic block heads a simple IF-THEN or IF-THEN-ELSE
    5278              :    block.  If so, we'll try to convert the insns to not require the branch.
    5279              :    Return TRUE if we were successful at converting the block.  */
    5280              : 
    5281              : static bool
    5282            0 : cond_exec_find_if_block (struct ce_if_block * ce_info)
    5283              : {
    5284            0 :   basic_block test_bb = ce_info->test_bb;
    5285            0 :   basic_block then_bb = ce_info->then_bb;
    5286            0 :   basic_block else_bb = ce_info->else_bb;
    5287            0 :   basic_block join_bb = NULL_BLOCK;
    5288            0 :   edge cur_edge;
    5289            0 :   basic_block next;
    5290            0 :   edge_iterator ei;
    5291              : 
    5292            0 :   ce_info->last_test_bb = test_bb;
    5293              : 
    5294              :   /* We only ever should get here after reload,
    5295              :      and if we have conditional execution.  */
    5296            0 :   gcc_assert (reload_completed && targetm.have_conditional_execution ());
    5297              : 
    5298              :   /* Discover if any fall through predecessors of the current test basic block
    5299              :      were && tests (which jump to the else block) or || tests (which jump to
    5300              :      the then block).  */
    5301            0 :   if (single_pred_p (test_bb)
    5302            0 :       && single_pred_edge (test_bb)->flags == EDGE_FALLTHRU)
    5303              :     {
    5304            0 :       basic_block bb = single_pred (test_bb);
    5305            0 :       basic_block target_bb;
    5306            0 :       int max_insns = MAX_CONDITIONAL_EXECUTE;
    5307            0 :       int n_insns;
    5308              : 
    5309              :       /* Determine if the preceding block is an && or || block.  */
    5310            0 :       if ((n_insns = block_jumps_and_fallthru (bb, else_bb)) >= 0)
    5311              :         {
    5312            0 :           ce_info->and_and_p = true;
    5313            0 :           target_bb = else_bb;
    5314              :         }
    5315            0 :       else if ((n_insns = block_jumps_and_fallthru (bb, then_bb)) >= 0)
    5316              :         {
    5317            0 :           ce_info->and_and_p = false;
    5318            0 :           target_bb = then_bb;
    5319              :         }
    5320              :       else
    5321              :         target_bb = NULL_BLOCK;
    5322              : 
    5323            0 :       if (target_bb && n_insns <= max_insns)
    5324              :         {
    5325            0 :           int total_insns = 0;
    5326            0 :           int blocks = 0;
    5327              : 
    5328            0 :           ce_info->last_test_bb = test_bb;
    5329              : 
    5330              :           /* Found at least one && or || block, look for more.  */
    5331            0 :           do
    5332              :             {
    5333            0 :               ce_info->test_bb = test_bb = bb;
    5334            0 :               total_insns += n_insns;
    5335            0 :               blocks++;
    5336              : 
    5337            0 :               if (!single_pred_p (bb))
    5338              :                 break;
    5339              : 
    5340            0 :               bb = single_pred (bb);
    5341            0 :               n_insns = block_jumps_and_fallthru (bb, target_bb);
    5342              :             }
    5343            0 :           while (n_insns >= 0 && (total_insns + n_insns) <= max_insns);
    5344              : 
    5345            0 :           ce_info->num_multiple_test_blocks = blocks;
    5346            0 :           ce_info->num_multiple_test_insns = total_insns;
    5347              : 
    5348            0 :           if (ce_info->and_and_p)
    5349            0 :             ce_info->num_and_and_blocks = blocks;
    5350              :           else
    5351            0 :             ce_info->num_or_or_blocks = blocks;
    5352              :         }
    5353              :     }
    5354              : 
    5355              :   /* The THEN block of an IF-THEN combo must have exactly one predecessor,
    5356              :      other than any || blocks which jump to the THEN block.  */
    5357            0 :   if ((EDGE_COUNT (then_bb->preds) - ce_info->num_or_or_blocks) != 1)
    5358              :     return false;
    5359              : 
    5360              :   /* The edges of the THEN and ELSE blocks cannot have complex edges.  */
    5361            0 :   FOR_EACH_EDGE (cur_edge, ei, then_bb->preds)
    5362              :     {
    5363            0 :       if (cur_edge->flags & EDGE_COMPLEX)
    5364              :         return false;
    5365              :     }
    5366              : 
    5367            0 :   FOR_EACH_EDGE (cur_edge, ei, else_bb->preds)
    5368              :     {
    5369            0 :       if (cur_edge->flags & EDGE_COMPLEX)
    5370              :         return false;
    5371              :     }
    5372              : 
    5373              :   /* The THEN block of an IF-THEN combo must have zero or one successors.  */
    5374            0 :   if (EDGE_COUNT (then_bb->succs) > 0
    5375            0 :       && (!single_succ_p (then_bb)
    5376            0 :           || (single_succ_edge (then_bb)->flags & EDGE_COMPLEX)
    5377            0 :           || (epilogue_completed
    5378            0 :               && tablejump_p (BB_END (then_bb), NULL, NULL))))
    5379            0 :     return false;
    5380              : 
    5381              :   /* If the THEN block has no successors, conditional execution can still
    5382              :      make a conditional call.  Don't do this unless the ELSE block has
    5383              :      only one incoming edge -- the CFG manipulation is too ugly otherwise.
    5384              :      Check for the last insn of the THEN block being an indirect jump, which
    5385              :      is listed as not having any successors, but confuses the rest of the CE
    5386              :      code processing.  ??? we should fix this in the future.  */
    5387            0 :   if (EDGE_COUNT (then_bb->succs) == 0)
    5388              :     {
    5389            0 :       if (single_pred_p (else_bb) && else_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
    5390              :         {
    5391            0 :           rtx_insn *last_insn = BB_END (then_bb);
    5392              : 
    5393            0 :           while (last_insn
    5394            0 :                  && NOTE_P (last_insn)
    5395            0 :                  && last_insn != BB_HEAD (then_bb))
    5396            0 :             last_insn = PREV_INSN (last_insn);
    5397              : 
    5398            0 :           if (last_insn
    5399            0 :               && JUMP_P (last_insn)
    5400            0 :               && ! simplejump_p (last_insn))
    5401              :             return false;
    5402              : 
    5403              :           join_bb = else_bb;
    5404              :           else_bb = NULL_BLOCK;
    5405              :         }
    5406              :       else
    5407              :         return false;
    5408              :     }
    5409              : 
    5410              :   /* If the THEN block's successor is the other edge out of the TEST block,
    5411              :      then we have an IF-THEN combo without an ELSE.  */
    5412            0 :   else if (single_succ (then_bb) == else_bb)
    5413              :     {
    5414              :       join_bb = else_bb;
    5415              :       else_bb = NULL_BLOCK;
    5416              :     }
    5417              : 
    5418              :   /* If the THEN and ELSE block meet in a subsequent block, and the ELSE
    5419              :      has exactly one predecessor and one successor, and the outgoing edge
    5420              :      is not complex, then we have an IF-THEN-ELSE combo.  */
    5421            0 :   else if (single_succ_p (else_bb)
    5422            0 :            && single_succ (then_bb) == single_succ (else_bb)
    5423            0 :            && single_pred_p (else_bb)
    5424            0 :            && !(single_succ_edge (else_bb)->flags & EDGE_COMPLEX)
    5425            0 :            && !(epilogue_completed
    5426            0 :                 && tablejump_p (BB_END (else_bb), NULL, NULL)))
    5427            0 :     join_bb = single_succ (else_bb);
    5428              : 
    5429              :   /* Otherwise it is not an IF-THEN or IF-THEN-ELSE combination.  */
    5430              :   else
    5431            0 :     return false;
    5432              : 
    5433            0 :   num_possible_if_blocks++;
    5434              : 
    5435            0 :   if (dump_file)
    5436              :     {
    5437            0 :       fprintf (dump_file,
    5438              :                "\nIF-THEN%s block found, pass %d, start block %d "
    5439              :                "[insn %d], then %d [%d]",
    5440              :                (else_bb) ? "-ELSE" : "",
    5441              :                ce_info->pass,
    5442              :                test_bb->index,
    5443            0 :                BB_HEAD (test_bb) ? (int)INSN_UID (BB_HEAD (test_bb)) : -1,
    5444              :                then_bb->index,
    5445            0 :                BB_HEAD (then_bb) ? (int)INSN_UID (BB_HEAD (then_bb)) : -1);
    5446              : 
    5447            0 :       if (else_bb)
    5448            0 :         fprintf (dump_file, ", else %d [%d]",
    5449              :                  else_bb->index,
    5450            0 :                  BB_HEAD (else_bb) ? (int)INSN_UID (BB_HEAD (else_bb)) : -1);
    5451              : 
    5452            0 :       fprintf (dump_file, ", join %d [%d]",
    5453              :                join_bb->index,
    5454            0 :                BB_HEAD (join_bb) ? (int)INSN_UID (BB_HEAD (join_bb)) : -1);
    5455              : 
    5456            0 :       if (ce_info->num_multiple_test_blocks > 0)
    5457            0 :         fprintf (dump_file, ", %d %s block%s last test %d [%d]",
    5458              :                  ce_info->num_multiple_test_blocks,
    5459            0 :                  (ce_info->and_and_p) ? "&&" : "||",
    5460              :                  (ce_info->num_multiple_test_blocks == 1) ? "" : "s",
    5461              :                  ce_info->last_test_bb->index,
    5462            0 :                  ((BB_HEAD (ce_info->last_test_bb))
    5463            0 :                   ? (int)INSN_UID (BB_HEAD (ce_info->last_test_bb))
    5464              :                   : -1));
    5465              : 
    5466            0 :       fputc ('\n', dump_file);
    5467              :     }
    5468              : 
    5469              :   /* Make sure IF, THEN, and ELSE, blocks are adjacent.  Actually, we get the
    5470              :      first condition for free, since we've already asserted that there's a
    5471              :      fallthru edge from IF to THEN.  Likewise for the && and || blocks, since
    5472              :      we checked the FALLTHRU flag, those are already adjacent to the last IF
    5473              :      block.  */
    5474              :   /* ??? As an enhancement, move the ELSE block.  Have to deal with
    5475              :      BLOCK notes, if by no other means than backing out the merge if they
    5476              :      exist.  Sticky enough I don't want to think about it now.  */
    5477            0 :   next = then_bb;
    5478            0 :   if (else_bb && (next = next->next_bb) != else_bb)
    5479              :     return false;
    5480            0 :   if ((next = next->next_bb) != join_bb
    5481            0 :       && join_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
    5482              :     {
    5483            0 :       if (else_bb)
    5484              :         join_bb = NULL;
    5485              :       else
    5486              :         return false;
    5487              :     }
    5488              : 
    5489              :   /* Do the real work.  */
    5490              : 
    5491            0 :   ce_info->else_bb = else_bb;
    5492            0 :   ce_info->join_bb = join_bb;
    5493              : 
    5494              :   /* If we have && and || tests, try to first handle combining the && and ||
    5495              :      tests into the conditional code, and if that fails, go back and handle
    5496              :      it without the && and ||, which at present handles the && case if there
    5497              :      was no ELSE block.  */
    5498            0 :   if (cond_exec_process_if_block (ce_info, true))
    5499              :     return true;
    5500              : 
    5501            0 :   if (ce_info->num_multiple_test_blocks)
    5502              :     {
    5503            0 :       cancel_changes (0);
    5504              : 
    5505            0 :       if (cond_exec_process_if_block (ce_info, false))
    5506              :         return true;
    5507              :     }
    5508              : 
    5509              :   return false;
    5510              : }
    5511              : 
    5512              : /* Convert a branch over a trap, or a branch
    5513              :    to a trap, into a conditional trap.  */
    5514              : 
    5515              : static bool
    5516            0 : find_cond_trap (basic_block test_bb, edge then_edge, edge else_edge)
    5517              : {
    5518            0 :   basic_block then_bb = then_edge->dest;
    5519            0 :   basic_block else_bb = else_edge->dest;
    5520            0 :   basic_block other_bb, trap_bb;
    5521            0 :   rtx_insn *trap, *jump;
    5522            0 :   rtx cond;
    5523            0 :   rtx_insn *cond_earliest;
    5524              : 
    5525              :   /* Locate the block with the trap instruction.  */
    5526              :   /* ??? While we look for no successors, we really ought to allow
    5527              :      EH successors.  Need to fix merge_if_block for that to work.  */
    5528            0 :   if ((trap = block_has_only_trap (then_bb)) != NULL)
    5529              :     trap_bb = then_bb, other_bb = else_bb;
    5530            0 :   else if ((trap = block_has_only_trap (else_bb)) != NULL)
    5531              :     trap_bb = else_bb, other_bb = then_bb;
    5532              :   else
    5533              :     return false;
    5534              : 
    5535            0 :   if (dump_file)
    5536              :     {
    5537            0 :       fprintf (dump_file, "\nTRAP-IF block found, start %d, trap %d\n",
    5538              :                test_bb->index, trap_bb->index);
    5539              :     }
    5540              : 
    5541              :   /* If this is not a standard conditional jump, we can't parse it.  */
    5542            0 :   jump = BB_END (test_bb);
    5543            0 :   cond = noce_get_condition (jump, &cond_earliest, then_bb == trap_bb);
    5544            0 :   if (! cond)
    5545              :     return false;
    5546              : 
    5547              :   /* If the conditional jump is more than just a conditional jump, then
    5548              :      we cannot do if-conversion on this block.  Give up for returnjump_p,
    5549              :      changing a conditional return followed by unconditional trap for
    5550              :      conditional trap followed by unconditional return is likely not
    5551              :      beneficial and harder to handle.  */
    5552            0 :   if (! onlyjump_p (jump) || returnjump_p (jump))
    5553            0 :     return false;
    5554              : 
    5555              :   /* We must be comparing objects whose modes imply the size.  */
    5556            0 :   if (GET_MODE (XEXP (cond, 0)) == BLKmode)
    5557              :     return false;
    5558              : 
    5559              :   /* Attempt to generate the conditional trap.  */
    5560            0 :   rtx_insn *seq = gen_cond_trap (GET_CODE (cond), copy_rtx (XEXP (cond, 0)),
    5561              :                                  copy_rtx (XEXP (cond, 1)),
    5562            0 :                                  TRAP_CODE (PATTERN (trap)));
    5563            0 :   if (seq == NULL)
    5564              :     return false;
    5565              : 
    5566              :   /* If that results in an invalid insn, back out.  */
    5567            0 :   for (rtx_insn *x = seq; x; x = NEXT_INSN (x))
    5568            0 :     if (reload_completed
    5569            0 :         ? !valid_insn_p (x)
    5570            0 :         : recog_memoized (x) < 0)
    5571              :       return false;
    5572              : 
    5573              :   /* Emit the new insns before cond_earliest.  */
    5574            0 :   emit_insn_before_setloc (seq, cond_earliest, INSN_LOCATION (trap));
    5575              : 
    5576              :   /* Delete the trap block if possible.  */
    5577            0 :   remove_edge (trap_bb == then_bb ? then_edge : else_edge);
    5578            0 :   df_set_bb_dirty (test_bb);
    5579            0 :   df_set_bb_dirty (then_bb);
    5580            0 :   df_set_bb_dirty (else_bb);
    5581              : 
    5582            0 :   if (EDGE_COUNT (trap_bb->preds) == 0)
    5583              :     {
    5584            0 :       delete_basic_block (trap_bb);
    5585            0 :       num_true_changes++;
    5586              :     }
    5587              : 
    5588              :   /* Wire together the blocks again.  */
    5589            0 :   if (current_ir_type () == IR_RTL_CFGLAYOUT)
    5590            0 :     single_succ_edge (test_bb)->flags |= EDGE_FALLTHRU;
    5591            0 :   else if (trap_bb == then_bb)
    5592              :     {
    5593            0 :       rtx lab = JUMP_LABEL (jump);
    5594            0 :       rtx_insn *seq = targetm.gen_jump (lab);
    5595            0 :       rtx_jump_insn *newjump = emit_jump_insn_after (seq, jump);
    5596            0 :       LABEL_NUSES (lab) += 1;
    5597            0 :       JUMP_LABEL (newjump) = lab;
    5598            0 :       emit_barrier_after (newjump);
    5599              :     }
    5600            0 :   delete_insn (jump);
    5601              : 
    5602            0 :   if (can_merge_blocks_p (test_bb, other_bb))
    5603              :     {
    5604            0 :       merge_blocks (test_bb, other_bb);
    5605            0 :       num_true_changes++;
    5606              :     }
    5607              : 
    5608            0 :   num_updated_if_blocks++;
    5609            0 :   return true;
    5610              : }
    5611              : 
    5612              : /* Subroutine of find_cond_trap: if BB contains only a trap insn,
    5613              :    return it.  */
    5614              : 
    5615              : static rtx_insn *
    5616            0 : block_has_only_trap (basic_block bb)
    5617              : {
    5618            0 :   rtx_insn *trap;
    5619              : 
    5620              :   /* We're not the exit block.  */
    5621            0 :   if (bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
    5622              :     return NULL;
    5623              : 
    5624              :   /* The block must have no successors.  */
    5625            0 :   if (EDGE_COUNT (bb->succs) > 0)
    5626              :     return NULL;
    5627              : 
    5628              :   /* The only instruction in the THEN block must be the trap.  */
    5629            0 :   trap = first_active_insn (bb);
    5630            0 :   if (! (trap == BB_END (bb)
    5631            0 :          && GET_CODE (PATTERN (trap)) == TRAP_IF
    5632            0 :          && TRAP_CONDITION (PATTERN (trap)) == const_true_rtx))
    5633            0 :     return NULL;
    5634              : 
    5635              :   return trap;
    5636              : }
    5637              : 
    5638              : /* Look for IF-THEN-ELSE cases in which one of THEN or ELSE is
    5639              :    transformable, but not necessarily the other.  There need be no
    5640              :    JOIN block.
    5641              : 
    5642              :    Return TRUE if we were successful at converting the block.
    5643              : 
    5644              :    Cases we'd like to look at:
    5645              : 
    5646              :    (1)
    5647              :         if (test) goto over; // x not live
    5648              :         x = a;
    5649              :         goto label;
    5650              :         over:
    5651              : 
    5652              :    becomes
    5653              : 
    5654              :         x = a;
    5655              :         if (! test) goto label;
    5656              : 
    5657              :    (2)
    5658              :         if (test) goto E; // x not live
    5659              :         x = big();
    5660              :         goto L;
    5661              :         E:
    5662              :         x = b;
    5663              :         goto M;
    5664              : 
    5665              :    becomes
    5666              : 
    5667              :         x = b;
    5668              :         if (test) goto M;
    5669              :         x = big();
    5670              :         goto L;
    5671              : 
    5672              :    (3) // This one's really only interesting for targets that can do
    5673              :        // multiway branching, e.g. IA-64 BBB bundles.  For other targets
    5674              :        // it results in multiple branches on a cache line, which often
    5675              :        // does not sit well with predictors.
    5676              : 
    5677              :         if (test1) goto E; // predicted not taken
    5678              :         x = a;
    5679              :         if (test2) goto F;
    5680              :         ...
    5681              :         E:
    5682              :         x = b;
    5683              :         J:
    5684              : 
    5685              :    becomes
    5686              : 
    5687              :         x = a;
    5688              :         if (test1) goto E;
    5689              :         if (test2) goto F;
    5690              : 
    5691              :    Notes:
    5692              : 
    5693              :    (A) Don't do (2) if the branch is predicted against the block we're
    5694              :    eliminating.  Do it anyway if we can eliminate a branch; this requires
    5695              :    that the sole successor of the eliminated block postdominate the other
    5696              :    side of the if.
    5697              : 
    5698              :    (B) With CE, on (3) we can steal from both sides of the if, creating
    5699              : 
    5700              :         if (test1) x = a;
    5701              :         if (!test1) x = b;
    5702              :         if (test1) goto J;
    5703              :         if (test2) goto F;
    5704              :         ...
    5705              :         J:
    5706              : 
    5707              :    Again, this is most useful if J postdominates.
    5708              : 
    5709              :    (C) CE substitutes for helpful life information.
    5710              : 
    5711              :    (D) These heuristics need a lot of work.  */
    5712              : 
    5713              : /* Tests for case 1 above.  */
    5714              : 
    5715              : static bool
    5716     14238508 : find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
    5717              : {
    5718     14238508 :   basic_block then_bb = then_edge->dest;
    5719     14238508 :   basic_block else_bb = else_edge->dest;
    5720     14238508 :   basic_block new_bb;
    5721     14238508 :   int then_bb_index;
    5722     14238508 :   profile_probability then_prob;
    5723     14238508 :   rtx else_target = NULL_RTX;
    5724              : 
    5725              :   /* If we are partitioning hot/cold basic blocks, we don't want to
    5726              :      mess up unconditional or indirect jumps that cross between hot
    5727              :      and cold sections.
    5728              : 
    5729              :      Basic block partitioning may result in some jumps that appear to
    5730              :      be optimizable (or blocks that appear to be mergeable), but which really
    5731              :      must be left untouched (they are required to make it safely across
    5732              :      partition boundaries).  See  the comments at the top of
    5733              :      bb-reorder.cc:partition_hot_cold_basic_blocks for complete details.  */
    5734              : 
    5735     14238508 :   if ((BB_END (then_bb)
    5736     14238508 :        && JUMP_P (BB_END (then_bb))
    5737      7364686 :        && CROSSING_JUMP_P (BB_END (then_bb)))
    5738     14003501 :       || (JUMP_P (BB_END (test_bb))
    5739     14003501 :           && CROSSING_JUMP_P (BB_END (test_bb)))
    5740     28129383 :       || (BB_END (else_bb)
    5741     13890875 :           && JUMP_P (BB_END (else_bb))
    5742      7087337 :           && CROSSING_JUMP_P (BB_END (else_bb))))
    5743              :     return false;
    5744              : 
    5745              :   /* Verify test_bb ends in a conditional jump with no other side-effects.  */
    5746     13861402 :   if (!onlyjump_p (BB_END (test_bb)))
    5747              :     return false;
    5748              : 
    5749              :   /* THEN has one successor.  */
    5750     20634429 :   if (!single_succ_p (then_bb))
    5751              :     return false;
    5752              : 
    5753              :   /* THEN does not fall through, but is not strange either.  */
    5754      6418859 :   if (single_succ_edge (then_bb)->flags & (EDGE_COMPLEX | EDGE_FALLTHRU))
    5755              :     return false;
    5756              : 
    5757              :   /* THEN has one predecessor.  */
    5758     15355089 :   if (!single_pred_p (then_bb))
    5759              :     return false;
    5760              : 
    5761              :   /* THEN must do something.  */
    5762      1139519 :   if (forwarder_block_p (then_bb))
    5763              :     return false;
    5764              : 
    5765       731015 :   num_possible_if_blocks++;
    5766       731015 :   if (dump_file)
    5767            8 :     fprintf (dump_file,
    5768              :              "\nIF-CASE-1 found, start %d, then %d\n",
    5769              :              test_bb->index, then_bb->index);
    5770              : 
    5771       731015 :   then_prob = then_edge->probability.invert ();
    5772              : 
    5773              :   /* We're speculating from the THEN path, we want to make sure the cost
    5774              :      of speculation is within reason.  */
    5775      1385766 :   if (! cheap_bb_rtx_cost_p (then_bb, then_prob,
    5776      1385766 :         COSTS_N_INSNS (BRANCH_COST (optimize_bb_for_speed_p (then_edge->src),
    5777              :                                     predictable_edge_p (then_edge)))))
    5778              :     return false;
    5779              : 
    5780       149349 :   if (else_bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
    5781              :     {
    5782            0 :       rtx_insn *jump = BB_END (else_edge->src);
    5783            0 :       gcc_assert (JUMP_P (jump));
    5784            0 :       else_target = JUMP_LABEL (jump);
    5785              :     }
    5786              : 
    5787              :   /* Registers set are dead, or are predicable.  */
    5788       149349 :   if (! dead_or_predicable (test_bb, then_bb, else_bb,
    5789              :                             single_succ_edge (then_bb), true))
    5790              :     return false;
    5791              : 
    5792              :   /* Conversion went ok, including moving the insns and fixing up the
    5793              :      jump.  Adjust the CFG to match.  */
    5794              : 
    5795              :   /* We can avoid creating a new basic block if then_bb is immediately
    5796              :      followed by else_bb, i.e. deleting then_bb allows test_bb to fall
    5797              :      through to else_bb.  */
    5798              : 
    5799        22938 :   if (then_bb->next_bb == else_bb
    5800        10303 :       && then_bb->prev_bb == test_bb
    5801        10303 :       && else_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
    5802              :     {
    5803        10303 :       redirect_edge_succ (FALLTHRU_EDGE (test_bb), else_bb);
    5804        10303 :       new_bb = 0;
    5805              :     }
    5806        12635 :   else if (else_bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
    5807            0 :     new_bb = force_nonfallthru_and_redirect (FALLTHRU_EDGE (test_bb),
    5808              :                                              else_bb, else_target);
    5809              :   else
    5810        12635 :     new_bb = redirect_edge_and_branch_force (FALLTHRU_EDGE (test_bb),
    5811              :                                              else_bb);
    5812              : 
    5813        22938 :   df_set_bb_dirty (test_bb);
    5814        22938 :   df_set_bb_dirty (else_bb);
    5815              : 
    5816        22938 :   then_bb_index = then_bb->index;
    5817        22938 :   delete_basic_block (then_bb);
    5818              : 
    5819              :   /* Make rest of code believe that the newly created block is the THEN_BB
    5820              :      block we removed.  */
    5821        22938 :   if (new_bb)
    5822              :     {
    5823        12635 :       df_bb_replace (then_bb_index, new_bb);
    5824              :       /* This should have been done above via force_nonfallthru_and_redirect
    5825              :          (possibly called from redirect_edge_and_branch_force).  */
    5826        12635 :       gcc_checking_assert (BB_PARTITION (new_bb) == BB_PARTITION (test_bb));
    5827              :     }
    5828              : 
    5829        22938 :   num_true_changes++;
    5830        22938 :   num_updated_if_blocks++;
    5831        22938 :   return true;
    5832              : }
    5833              : 
    5834              : /* Test for case 2 above.  */
    5835              : 
    5836              : static bool
    5837     14215570 : find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge)
    5838              : {
    5839     14215570 :   basic_block then_bb = then_edge->dest;
    5840     14215570 :   basic_block else_bb = else_edge->dest;
    5841     14215570 :   edge else_succ;
    5842     14215570 :   profile_probability then_prob, else_prob;
    5843              : 
    5844              :   /* We do not want to speculate (empty) loop latches.  */
    5845     14215570 :   if (current_loops
    5846      5513851 :       && else_bb->loop_father->latch == else_bb)
    5847              :     return false;
    5848              : 
    5849              :   /* If we are partitioning hot/cold basic blocks, we don't want to
    5850              :      mess up unconditional or indirect jumps that cross between hot
    5851              :      and cold sections.
    5852              : 
    5853              :      Basic block partitioning may result in some jumps that appear to
    5854              :      be optimizable (or blocks that appear to be mergeable), but which really
    5855              :      must be left untouched (they are required to make it safely across
    5856              :      partition boundaries).  See  the comments at the top of
    5857              :      bb-reorder.cc:partition_hot_cold_basic_blocks for complete details.  */
    5858              : 
    5859     14063497 :   if ((BB_END (then_bb)
    5860     14063497 :        && JUMP_P (BB_END (then_bb))
    5861      7267958 :        && CROSSING_JUMP_P (BB_END (then_bb)))
    5862     13828490 :       || (JUMP_P (BB_END (test_bb))
    5863     13828490 :           && CROSSING_JUMP_P (BB_END (test_bb)))
    5864     27779361 :       || (BB_END (else_bb)
    5865     13715864 :           && JUMP_P (BB_END (else_bb))
    5866      6946188 :           && CROSSING_JUMP_P (BB_END (else_bb))))
    5867              :     return false;
    5868              : 
    5869              :   /* Verify test_bb ends in a conditional jump with no other side-effects.  */
    5870     13686391 :   if (!onlyjump_p (BB_END (test_bb)))
    5871              :     return false;
    5872              : 
    5873              :   /* ELSE has one successor.  */
    5874     19800317 :   if (!single_succ_p (else_bb))
    5875              :     return false;
    5876              :   else
    5877      5714728 :     else_succ = single_succ_edge (else_bb);
    5878              : 
    5879              :   /* ELSE outgoing edge is not complex.  */
    5880      5714728 :   if (else_succ->flags & EDGE_COMPLEX)
    5881              :     return false;
    5882              : 
    5883              :   /* ELSE has one predecessor.  */
    5884     16941792 :   if (!single_pred_p (else_bb))
    5885              :     return false;
    5886              : 
    5887              :   /* THEN is not EXIT.  */
    5888      2856203 :   if (then_bb->index < NUM_FIXED_BLOCKS)
    5889              :     return false;
    5890              : 
    5891      2856203 :   else_prob = else_edge->probability;
    5892      2856203 :   then_prob = else_prob.invert ();
    5893              : 
    5894              :   /* ELSE is predicted or SUCC(ELSE) postdominates THEN.  */
    5895      2856203 :   if (else_prob > then_prob)
    5896              :     ;
    5897      1901346 :   else if (else_succ->dest->index < NUM_FIXED_BLOCKS
    5898      1901346 :            || dominated_by_p (CDI_POST_DOMINATORS, then_bb,
    5899              :                               else_succ->dest))
    5900              :     ;
    5901              :   else
    5902              :     return false;
    5903              : 
    5904      2248753 :   num_possible_if_blocks++;
    5905      2248753 :   if (dump_file)
    5906           44 :     fprintf (dump_file,
    5907              :              "\nIF-CASE-2 found, start %d, else %d\n",
    5908              :              test_bb->index, else_bb->index);
    5909              : 
    5910              :   /* We're speculating from the ELSE path, we want to make sure the cost
    5911              :      of speculation is within reason.  */
    5912      4326656 :   if (! cheap_bb_rtx_cost_p (else_bb, else_prob,
    5913      4326656 :         COSTS_N_INSNS (BRANCH_COST (optimize_bb_for_speed_p (else_edge->src),
    5914              :                                     predictable_edge_p (else_edge)))))
    5915              :     return false;
    5916              : 
    5917              :   /* Registers set are dead, or are predicable.  */
    5918       446645 :   if (! dead_or_predicable (test_bb, else_bb, then_bb, else_succ, false))
    5919              :     return false;
    5920              : 
    5921              :   /* Conversion went ok, including moving the insns and fixing up the
    5922              :      jump.  Adjust the CFG to match.  */
    5923              : 
    5924       129981 :   df_set_bb_dirty (test_bb);
    5925       129981 :   df_set_bb_dirty (then_bb);
    5926       129981 :   delete_basic_block (else_bb);
    5927              : 
    5928       129981 :   num_true_changes++;
    5929       129981 :   num_updated_if_blocks++;
    5930              : 
    5931              :   /* ??? We may now fallthru from one of THEN's successors into a join
    5932              :      block.  Rerun cleanup_cfg?  Examine things manually?  Wait?  */
    5933              : 
    5934       129981 :   return true;
    5935              : }
    5936              : 
    5937              : /* Used by the code above to perform the actual rtl transformations.
    5938              :    Return TRUE if successful.
    5939              : 
    5940              :    TEST_BB is the block containing the conditional branch.  MERGE_BB
    5941              :    is the block containing the code to manipulate.  DEST_EDGE is an
    5942              :    edge representing a jump to the join block; after the conversion,
    5943              :    TEST_BB should be branching to its destination.
    5944              :    REVERSEP is true if the sense of the branch should be reversed.  */
    5945              : 
    5946              : static bool
    5947       595994 : dead_or_predicable (basic_block test_bb, basic_block merge_bb,
    5948              :                     basic_block other_bb, edge dest_edge, bool reversep)
    5949              : {
    5950       595994 :   basic_block new_dest = dest_edge->dest;
    5951       595994 :   rtx_insn *head, *end, *jump;
    5952       595994 :   rtx_insn *earliest = NULL;
    5953       595994 :   rtx old_dest;
    5954       595994 :   bitmap merge_set = NULL;
    5955              :   /* Number of pending changes.  */
    5956       595994 :   int n_validated_changes = 0;
    5957       595994 :   rtx new_dest_label = NULL_RTX;
    5958              : 
    5959       595994 :   jump = BB_END (test_bb);
    5960              : 
    5961              :   /* Find the extent of the real code in the merge block.  */
    5962       595994 :   head = BB_HEAD (merge_bb);
    5963       595994 :   end = BB_END (merge_bb);
    5964              : 
    5965       725046 :   while (DEBUG_INSN_P (end) && end != head)
    5966       129052 :     end = PREV_INSN (end);
    5967              : 
    5968              :   /* If merge_bb ends with a tablejump, predicating/moving insn's
    5969              :      into test_bb and then deleting merge_bb will result in the jumptable
    5970              :      that follows merge_bb being removed along with merge_bb and then we
    5971              :      get an unresolved reference to the jumptable.  */
    5972       595994 :   if (tablejump_p (end, NULL, NULL))
    5973              :     return false;
    5974              : 
    5975       595994 :   if (LABEL_P (head))
    5976       446700 :     head = NEXT_INSN (head);
    5977       595994 :   while (DEBUG_INSN_P (head) && head != end)
    5978            0 :     head = NEXT_INSN (head);
    5979       595994 :   if (NOTE_P (head))
    5980              :     {
    5981       595994 :       if (head == end)
    5982              :         {
    5983       105051 :           head = end = NULL;
    5984       105051 :           goto no_body;
    5985              :         }
    5986       490943 :       head = NEXT_INSN (head);
    5987      1327232 :       while (DEBUG_INSN_P (head) && head != end)
    5988       345346 :         head = NEXT_INSN (head);
    5989              :     }
    5990              : 
    5991       490943 :   if (JUMP_P (end))
    5992              :     {
    5993       205315 :       if (!onlyjump_p (end))
    5994              :         return false;
    5995       163500 :       if (head == end)
    5996              :         {
    5997            4 :           head = end = NULL;
    5998            4 :           goto no_body;
    5999              :         }
    6000       163496 :       end = PREV_INSN (end);
    6001       429765 :       while (DEBUG_INSN_P (end) && end != head)
    6002       102773 :         end = PREV_INSN (end);
    6003              :     }
    6004              : 
    6005              :   /* Don't move frame-related insn across the conditional branch.  This
    6006              :      can lead to one of the paths of the branch having wrong unwind info.  */
    6007       449124 :   if (epilogue_completed)
    6008              :     {
    6009              :       rtx_insn *insn = head;
    6010        72175 :       while (1)
    6011              :         {
    6012       280866 :           if (INSN_P (insn) && RTX_FRAME_RELATED_P (insn))
    6013              :             return false;
    6014       273546 :           if (insn == end)
    6015              :             break;
    6016        72175 :           insn = NEXT_INSN (insn);
    6017        72175 :         }
    6018              :     }
    6019              : 
    6020              :   /* Disable handling dead code by conditional execution if the machine needs
    6021              :      to do anything funny with the tests, etc.  */
    6022              : #ifndef IFCVT_MODIFY_TESTS
    6023       441804 :   if (targetm.have_conditional_execution ())
    6024              :     {
    6025              :       /* In the conditional execution case, we have things easy.  We know
    6026              :          the condition is reversible.  We don't have to check life info
    6027              :          because we're going to conditionally execute the code anyway.
    6028              :          All that's left is making sure the insns involved can actually
    6029              :          be predicated.  */
    6030              : 
    6031            0 :       rtx cond;
    6032              : 
    6033              :       /* If the conditional jump is more than just a conditional jump,
    6034              :          then we cannot do conditional execution conversion on this block.  */
    6035            0 :       if (!onlyjump_p (jump))
    6036            0 :         goto nce;
    6037              : 
    6038            0 :       cond = cond_exec_get_condition (jump);
    6039            0 :       if (! cond)
    6040            0 :         goto nce;
    6041              : 
    6042            0 :       rtx note = find_reg_note (jump, REG_BR_PROB, NULL_RTX);
    6043            0 :       profile_probability prob_val
    6044            0 :           = (note ? profile_probability::from_reg_br_prob_note (XINT (note, 0))
    6045            0 :              : profile_probability::uninitialized ());
    6046              : 
    6047            0 :       if (reversep)
    6048              :         {
    6049            0 :           enum rtx_code rev = reversed_comparison_code (cond, jump);
    6050            0 :           if (rev == UNKNOWN)
    6051            0 :             return false;
    6052            0 :           cond = gen_rtx_fmt_ee (rev, GET_MODE (cond), XEXP (cond, 0),
    6053              :                                  XEXP (cond, 1));
    6054            0 :           prob_val = prob_val.invert ();
    6055              :         }
    6056              : 
    6057            0 :       if (cond_exec_process_insns (NULL, head, end, cond, prob_val, false)
    6058            0 :           && verify_changes (0))
    6059            0 :         n_validated_changes = num_validated_changes ();
    6060              :       else
    6061            0 :         cancel_changes (0);
    6062              : 
    6063            0 :       earliest = jump;
    6064              :     }
    6065       441804 :  nce:
    6066              : #endif
    6067              : 
    6068              :   /* If we allocated new pseudos (e.g. in the conditional move
    6069              :      expander called from noce_emit_cmove), we must resize the
    6070              :      array first.  */
    6071       441804 :   if (max_regno < max_reg_num ())
    6072        85870 :     max_regno = max_reg_num ();
    6073              : 
    6074              :   /* Try the NCE path if the CE path did not result in any changes.  */
    6075       441804 :   if (n_validated_changes == 0)
    6076              :     {
    6077       441804 :       rtx cond;
    6078       441804 :       rtx_insn *insn;
    6079       441804 :       regset live;
    6080       441804 :       bool success;
    6081              : 
    6082              :       /* In the non-conditional execution case, we have to verify that there
    6083              :          are no trapping operations, no calls, no references to memory, and
    6084              :          that any registers modified are dead at the branch site.  */
    6085              : 
    6086       441804 :       if (!any_condjump_p (jump))
    6087              :         return false;
    6088              : 
    6089              :       /* Find the extent of the conditional.  */
    6090       441804 :       cond = noce_get_condition (jump, &earliest, false);
    6091       441804 :       if (!cond)
    6092              :         return false;
    6093              : 
    6094       440999 :       live = BITMAP_ALLOC (&reg_obstack);
    6095       440999 :       simulate_backwards_to_point (merge_bb, live, end);
    6096       440999 :       success = can_move_insns_across (head, end, earliest, jump,
    6097              :                                        merge_bb, live,
    6098              :                                        df_get_live_in (other_bb), NULL);
    6099       440999 :       BITMAP_FREE (live);
    6100       440999 :       if (!success)
    6101              :         return false;
    6102              : 
    6103              :       /* Collect the set of registers set in MERGE_BB.  */
    6104       149721 :       merge_set = BITMAP_ALLOC (&reg_obstack);
    6105              : 
    6106       742558 :       FOR_BB_INSNS (merge_bb, insn)
    6107       592837 :         if (NONDEBUG_INSN_P (insn))
    6108       196815 :           df_simulate_find_defs (insn, merge_set);
    6109              : 
    6110              :       /* If shrink-wrapping, disable this optimization when test_bb is
    6111              :          the first basic block and merge_bb exits.  The idea is to not
    6112              :          move code setting up a return register as that may clobber a
    6113              :          register used to pass function parameters, which then must be
    6114              :          saved in caller-saved regs.  A caller-saved reg requires the
    6115              :          prologue, killing a shrink-wrap opportunity.  */
    6116       149720 :       if ((SHRINK_WRAPPING_ENABLED && !epilogue_completed)
    6117       117401 :           && ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb == test_bb
    6118        19232 :           && single_succ_p (new_dest)
    6119        13801 :           && single_succ (new_dest) == EXIT_BLOCK_PTR_FOR_FN (cfun)
    6120       162601 :           && bitmap_intersect_p (df_get_live_in (new_dest), merge_set))
    6121              :         {
    6122        12880 :           regset return_regs;
    6123        12880 :           unsigned int i;
    6124              : 
    6125        12880 :           return_regs = BITMAP_ALLOC (&reg_obstack);
    6126              : 
    6127              :           /* Start off with the intersection of regs used to pass
    6128              :              params and regs used to return values.  */
    6129      1210720 :           for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
    6130      1184960 :             if (FUNCTION_ARG_REGNO_P (i)
    6131      1184960 :                 && targetm.calls.function_value_regno_p (i))
    6132        67720 :               bitmap_set_bit (return_regs, INCOMING_REGNO (i));
    6133              : 
    6134        12880 :           bitmap_and_into (return_regs,
    6135        12880 :                            df_get_live_out (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
    6136        12880 :           bitmap_and_into (return_regs,
    6137        12880 :                            df_get_live_in (EXIT_BLOCK_PTR_FOR_FN (cfun)));
    6138        12880 :           if (!bitmap_empty_p (return_regs))
    6139              :             {
    6140         4849 :               FOR_BB_INSNS_REVERSE (new_dest, insn)
    6141         4298 :                 if (NONDEBUG_INSN_P (insn))
    6142              :                   {
    6143         2180 :                     df_ref def;
    6144              : 
    6145              :                     /* If this insn sets any reg in return_regs, add all
    6146              :                        reg uses to the set of regs we're interested in.  */
    6147         2763 :                     FOR_EACH_INSN_DEF (def, insn)
    6148         1691 :                       if (bitmap_bit_p (return_regs, DF_REF_REGNO (def)))
    6149              :                         {
    6150         1108 :                           df_simulate_uses (insn, return_regs);
    6151         1108 :                           break;
    6152              :                         }
    6153              :                   }
    6154          551 :               if (bitmap_intersect_p (merge_set, return_regs))
    6155              :                 {
    6156          533 :                   BITMAP_FREE (return_regs);
    6157          533 :                   BITMAP_FREE (merge_set);
    6158          533 :                   return false;
    6159              :                 }
    6160              :             }
    6161        12347 :           BITMAP_FREE (return_regs);
    6162              :         }
    6163              :     }
    6164              : 
    6165       254243 :  no_body:
    6166              :   /* We don't want to use normal invert_jump or redirect_jump because
    6167              :      we don't want to delete_insn called.  Also, we want to do our own
    6168              :      change group management.  */
    6169              : 
    6170       254243 :   old_dest = JUMP_LABEL (jump);
    6171       254243 :   if (other_bb != new_dest)
    6172              :     {
    6173       254223 :       if (!any_condjump_p (jump))
    6174            0 :         goto cancel;
    6175              : 
    6176       254223 :       if (JUMP_P (BB_END (dest_edge->src)))
    6177        24366 :         new_dest_label = JUMP_LABEL (BB_END (dest_edge->src));
    6178       229857 :       else if (new_dest == EXIT_BLOCK_PTR_FOR_FN (cfun))
    6179       101324 :         new_dest_label = ret_rtx;
    6180              :       else
    6181       128533 :         new_dest_label = block_label (new_dest);
    6182              : 
    6183       254223 :       rtx_jump_insn *jump_insn = as_a <rtx_jump_insn *> (jump);
    6184       254223 :       if (reversep
    6185       254223 :           ? ! invert_jump_1 (jump_insn, new_dest_label)
    6186       231285 :           : ! redirect_jump_1 (jump_insn, new_dest_label))
    6187            0 :         goto cancel;
    6188              :     }
    6189              : 
    6190       254243 :   if (verify_changes (n_validated_changes))
    6191       152919 :     confirm_change_group ();
    6192              :   else
    6193       101324 :     goto cancel;
    6194              : 
    6195       152919 :   if (other_bb != new_dest)
    6196              :     {
    6197       152899 :       redirect_jump_2 (as_a <rtx_jump_insn *> (jump), old_dest, new_dest_label,
    6198              :                        0, reversep);
    6199              : 
    6200       152899 :       redirect_edge_succ (BRANCH_EDGE (test_bb), new_dest);
    6201       152899 :       if (reversep)
    6202              :         {
    6203        22938 :           std::swap (BRANCH_EDGE (test_bb)->probability,
    6204        22938 :                      FALLTHRU_EDGE (test_bb)->probability);
    6205        22938 :           update_br_prob_note (test_bb);
    6206              :         }
    6207              :     }
    6208              : 
    6209              :   /* Move the insns out of MERGE_BB to before the branch.  */
    6210       152919 :   if (head != NULL)
    6211              :     {
    6212       149188 :       rtx_insn *insn;
    6213              : 
    6214       149188 :       if (end == BB_END (merge_bb))
    6215       112979 :         BB_END (merge_bb) = PREV_INSN (head);
    6216              : 
    6217              :       /* PR 21767: when moving insns above a conditional branch, the REG_EQUAL
    6218              :          notes being moved might become invalid.  */
    6219              :       insn = head;
    6220       184370 :       do
    6221              :         {
    6222       184370 :           rtx note;
    6223              : 
    6224       184370 :           if (! INSN_P (insn))
    6225         3120 :             continue;
    6226       181250 :           note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
    6227       181250 :           if (! note)
    6228       169551 :             continue;
    6229        11699 :           remove_note (insn, note);
    6230       219552 :         } while (insn != end && (insn = NEXT_INSN (insn)));
    6231              : 
    6232              :       /* PR46315: when moving insns above a conditional branch, the REG_EQUAL
    6233              :          notes referring to the registers being set might become invalid.  */
    6234       149188 :       if (merge_set)
    6235              :         {
    6236       149188 :           unsigned i;
    6237       149188 :           bitmap_iterator bi;
    6238              : 
    6239       336514 :           EXECUTE_IF_SET_IN_BITMAP (merge_set, 0, i, bi)
    6240       187326 :             remove_reg_equal_equiv_notes_for_regno (i);
    6241              : 
    6242       149188 :           BITMAP_FREE (merge_set);
    6243              :         }
    6244              : 
    6245       149188 :       reorder_insns (head, end, PREV_INSN (earliest));
    6246              :     }
    6247              : 
    6248              :   /* Remove the jump and edge if we can.  */
    6249       152919 :   if (other_bb == new_dest)
    6250              :     {
    6251           20 :       delete_insn (jump);
    6252           20 :       remove_edge (BRANCH_EDGE (test_bb));
    6253              :       /* ??? Can't merge blocks here, as then_bb is still in use.
    6254              :          At minimum, the merge will get done just before bb-reorder.  */
    6255              :     }
    6256              : 
    6257              :   return true;
    6258              : 
    6259       101324 :  cancel:
    6260       101324 :   cancel_changes (0);
    6261              : 
    6262       101324 :   if (merge_set)
    6263            0 :     BITMAP_FREE (merge_set);
    6264              : 
    6265              :   return false;
    6266              : }
    6267              : 
    6268              : /* Main entry point for all if-conversion.  AFTER_COMBINE is true if
    6269              :    we are after combine pass.  */
    6270              : 
    6271              : static void
    6272      3123053 : if_convert (bool after_combine)
    6273              : {
    6274      3123053 :   basic_block bb;
    6275      3123053 :   int pass;
    6276              : 
    6277      3123053 :   if (optimize == 1)
    6278              :     {
    6279       231177 :       df_live_add_problem ();
    6280       231177 :       df_live_set_all_dirty ();
    6281              :     }
    6282              : 
    6283              :   /* Record whether we are after combine pass.  */
    6284      3123053 :   ifcvt_after_combine = after_combine;
    6285      3123053 :   have_cbranchcc4 = (direct_optab_handler (cbranch_optab, CCmode)
    6286      3123053 :                      != CODE_FOR_nothing);
    6287      3123053 :   num_possible_if_blocks = 0;
    6288      3123053 :   num_updated_if_blocks = 0;
    6289      3123053 :   num_true_changes = 0;
    6290              : 
    6291      3123053 :   loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
    6292      3123053 :   mark_loop_exit_edges ();
    6293      3123053 :   loop_optimizer_finalize ();
    6294      3123053 :   free_dominance_info (CDI_DOMINATORS);
    6295              : 
    6296              :   /* Compute postdominators.  */
    6297      3123053 :   calculate_dominance_info (CDI_POST_DOMINATORS);
    6298              : 
    6299      3123053 :   df_set_flags (DF_LR_RUN_DCE);
    6300              : 
    6301              :   /* Go through each of the basic blocks looking for things to convert.  If we
    6302              :      have conditional execution, we make multiple passes to allow us to handle
    6303              :      IF-THEN{-ELSE} blocks within other IF-THEN{-ELSE} blocks.  */
    6304      3123053 :   pass = 0;
    6305      3285934 :   do
    6306              :     {
    6307      3285934 :       df_analyze ();
    6308              :       /* Only need to do dce on the first pass.  */
    6309      3285934 :       df_clear_flags (DF_LR_RUN_DCE);
    6310      3285934 :       cond_exec_changed_p = false;
    6311      3285934 :       pass++;
    6312              : 
    6313              : #ifdef IFCVT_MULTIPLE_DUMPS
    6314      3285934 :       if (dump_file && pass > 1)
    6315           19 :         fprintf (dump_file, "\n\n========== Pass %d ==========\n", pass);
    6316              : #endif
    6317              : 
    6318     42849368 :       FOR_EACH_BB_FN (bb, cfun)
    6319              :         {
    6320              :           basic_block new_bb;
    6321     39874126 :           while (!df_get_bb_dirty (bb)
    6322     78956294 :                  && (new_bb = find_if_header (bb, pass)) != NULL)
    6323              :             bb = new_bb;
    6324              :         }
    6325              : 
    6326              : #ifdef IFCVT_MULTIPLE_DUMPS
    6327      3285934 :       if (dump_file && cond_exec_changed_p)
    6328           19 :         print_rtl_with_bb (dump_file, get_insns (), dump_flags);
    6329              : #endif
    6330              :     }
    6331              :   while (cond_exec_changed_p);
    6332              : 
    6333              : #ifdef IFCVT_MULTIPLE_DUMPS
    6334      3123053 :   if (dump_file)
    6335           85 :     fprintf (dump_file, "\n\n========== no more changes\n");
    6336              : #endif
    6337              : 
    6338      3123053 :   free_dominance_info (CDI_POST_DOMINATORS);
    6339              : 
    6340      3123053 :   if (dump_file)
    6341           85 :     fflush (dump_file);
    6342              : 
    6343      3123053 :   clear_aux_for_blocks ();
    6344              : 
    6345              :   /* If we allocated new pseudos, we must resize the array for sched1.  */
    6346      3123053 :   if (max_regno < max_reg_num ())
    6347       627514 :     max_regno = max_reg_num ();
    6348              : 
    6349              :   /* Write the final stats.  */
    6350      3123053 :   if (dump_file && num_possible_if_blocks > 0)
    6351              :     {
    6352           59 :       fprintf (dump_file,
    6353              :                "\n%d possible IF blocks searched.\n",
    6354              :                num_possible_if_blocks);
    6355           59 :       fprintf (dump_file,
    6356              :                "%d IF blocks converted.\n",
    6357              :                num_updated_if_blocks);
    6358           59 :       fprintf (dump_file,
    6359              :                "%d true changes made.\n\n\n",
    6360              :                num_true_changes);
    6361              :     }
    6362              : 
    6363      3123053 :   if (optimize == 1)
    6364       231177 :     df_remove_problem (df_live);
    6365              : 
    6366              :   /* Some non-cold blocks may now be only reachable from cold blocks.
    6367              :      Fix that up.  */
    6368      3123053 :   fixup_partitions ();
    6369              : 
    6370      3123053 :   checking_verify_flow_info ();
    6371      3123053 : }
    6372              : 
    6373              : /* If-conversion and CFG cleanup.  */
    6374              : static void
    6375      1043685 : rest_of_handle_if_conversion (void)
    6376              : {
    6377      1043685 :   int flags = 0;
    6378              : 
    6379      1043685 :   if (flag_if_conversion)
    6380              :     {
    6381      1041015 :       if (dump_file)
    6382              :         {
    6383           33 :           dump_reg_info (dump_file);
    6384           33 :           dump_flow_info (dump_file, dump_flags);
    6385              :         }
    6386      1041015 :       cleanup_cfg (CLEANUP_EXPENSIVE);
    6387      1041015 :       if_convert (false);
    6388      1041015 :       if (num_updated_if_blocks)
    6389              :         /* Get rid of any dead CC-related instructions.  */
    6390      1043685 :         flags |= CLEANUP_FORCE_FAST_DCE;
    6391              :     }
    6392              : 
    6393      1043685 :   cleanup_cfg (flags);
    6394      1043685 : }
    6395              : 
    6396              : namespace {
    6397              : 
    6398              : const pass_data pass_data_rtl_ifcvt =
    6399              : {
    6400              :   RTL_PASS, /* type */
    6401              :   "ce1", /* name */
    6402              :   OPTGROUP_NONE, /* optinfo_flags */
    6403              :   TV_IFCVT, /* tv_id */
    6404              :   0, /* properties_required */
    6405              :   0, /* properties_provided */
    6406              :   0, /* properties_destroyed */
    6407              :   0, /* todo_flags_start */
    6408              :   TODO_df_finish, /* todo_flags_finish */
    6409              : };
    6410              : 
    6411              : class pass_rtl_ifcvt : public rtl_opt_pass
    6412              : {
    6413              : public:
    6414       285722 :   pass_rtl_ifcvt (gcc::context *ctxt)
    6415       571444 :     : rtl_opt_pass (pass_data_rtl_ifcvt, ctxt)
    6416              :   {}
    6417              : 
    6418              :   /* opt_pass methods: */
    6419      1471370 :   bool gate (function *) final override
    6420              :     {
    6421      1471370 :       return (optimize > 0) && dbg_cnt (if_conversion);
    6422              :     }
    6423              : 
    6424      1043685 :   unsigned int execute (function *) final override
    6425              :     {
    6426      1043685 :       rest_of_handle_if_conversion ();
    6427      1043685 :       return 0;
    6428              :     }
    6429              : 
    6430              : }; // class pass_rtl_ifcvt
    6431              : 
    6432              : } // anon namespace
    6433              : 
    6434              : rtl_opt_pass *
    6435       285722 : make_pass_rtl_ifcvt (gcc::context *ctxt)
    6436              : {
    6437       285722 :   return new pass_rtl_ifcvt (ctxt);
    6438              : }
    6439              : 
    6440              : 
    6441              : /* Rerun if-conversion, as combine may have simplified things enough
    6442              :    to now meet sequence length restrictions.  */
    6443              : 
    6444              : namespace {
    6445              : 
    6446              : const pass_data pass_data_if_after_combine =
    6447              : {
    6448              :   RTL_PASS, /* type */
    6449              :   "ce2", /* name */
    6450              :   OPTGROUP_NONE, /* optinfo_flags */
    6451              :   TV_IFCVT, /* tv_id */
    6452              :   0, /* properties_required */
    6453              :   0, /* properties_provided */
    6454              :   0, /* properties_destroyed */
    6455              :   0, /* todo_flags_start */
    6456              :   TODO_df_finish, /* todo_flags_finish */
    6457              : };
    6458              : 
    6459              : class pass_if_after_combine : public rtl_opt_pass
    6460              : {
    6461              : public:
    6462       285722 :   pass_if_after_combine (gcc::context *ctxt)
    6463       571444 :     : rtl_opt_pass (pass_data_if_after_combine, ctxt)
    6464              :   {}
    6465              : 
    6466              :   /* opt_pass methods: */
    6467      1471370 :   bool gate (function *) final override
    6468              :     {
    6469      1043686 :       return optimize > 0 && flag_if_conversion
    6470      2512386 :         && dbg_cnt (if_after_combine);
    6471              :     }
    6472              : 
    6473      1041015 :   unsigned int execute (function *) final override
    6474              :     {
    6475      1041015 :       if_convert (true);
    6476      1041015 :       return 0;
    6477              :     }
    6478              : 
    6479              : }; // class pass_if_after_combine
    6480              : 
    6481              : } // anon namespace
    6482              : 
    6483              : rtl_opt_pass *
    6484       285722 : make_pass_if_after_combine (gcc::context *ctxt)
    6485              : {
    6486       285722 :   return new pass_if_after_combine (ctxt);
    6487              : }
    6488              : 
    6489              : 
    6490              : namespace {
    6491              : 
    6492              : const pass_data pass_data_if_after_reload =
    6493              : {
    6494              :   RTL_PASS, /* type */
    6495              :   "ce3", /* name */
    6496              :   OPTGROUP_NONE, /* optinfo_flags */
    6497              :   TV_IFCVT2, /* tv_id */
    6498              :   0, /* properties_required */
    6499              :   0, /* properties_provided */
    6500              :   0, /* properties_destroyed */
    6501              :   0, /* todo_flags_start */
    6502              :   TODO_df_finish, /* todo_flags_finish */
    6503              : };
    6504              : 
    6505              : class pass_if_after_reload : public rtl_opt_pass
    6506              : {
    6507              : public:
    6508       285722 :   pass_if_after_reload (gcc::context *ctxt)
    6509       571444 :     : rtl_opt_pass (pass_data_if_after_reload, ctxt)
    6510              :   {}
    6511              : 
    6512              :   /* opt_pass methods: */
    6513      1471370 :   bool gate (function *) final override
    6514              :     {
    6515      1043686 :       return optimize > 0 && flag_if_conversion2
    6516      2512394 :         && dbg_cnt (if_after_reload);
    6517              :     }
    6518              : 
    6519      1041023 :   unsigned int execute (function *) final override
    6520              :     {
    6521      1041023 :       if_convert (true);
    6522      1041023 :       return 0;
    6523              :     }
    6524              : 
    6525              : }; // class pass_if_after_reload
    6526              : 
    6527              : } // anon namespace
    6528              : 
    6529              : rtl_opt_pass *
    6530       285722 : make_pass_if_after_reload (gcc::context *ctxt)
    6531              : {
    6532       285722 :   return new pass_if_after_reload (ctxt);
    6533              : }
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.