LCOV - code coverage report
Current view: top level - gcc - ifcvt.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 74.5 % 2768 2063
Test Date: 2026-07-11 15:47:05 Functions: 86.1 % 79 68
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      3057038 : cheap_bb_rtx_cost_p (const_basic_block bb,
     137              :                      profile_probability prob, int max_cost)
     138              : {
     139      3057038 :   int count = 0;
     140      3057038 :   rtx_insn *insn = BB_HEAD (bb);
     141      3057038 :   bool speed = optimize_bb_for_speed_p (bb);
     142      3057038 :   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      3057038 :   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      3005908 :     scale += REG_BR_PROB_BASE / 8;
     161              : 
     162              : 
     163      3057038 :   max_cost *= scale;
     164              : 
     165     12372298 :   while (1)
     166              :     {
     167     15429336 :       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      4576457 :           if (asm_noperands (PATTERN (insn)) >= 0)
     174              :             return false;
     175              : 
     176      4573699 :           int cost = insn_cost (insn, speed) * REG_BR_PROB_BASE;
     177      4573699 :           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      4523392 :           {
     189      4523392 :             rtx set = single_set (insn);
     190      4523392 :             if (set && STACK_REG_P (SET_DEST (set)))
     191              :               return false;
     192              :           }
     193              : #endif
     194              : 
     195      4519571 :           count += cost;
     196      4519571 :           if (count >= max_cost)
     197              :             return false;
     198              :         }
     199     10852879 :       else if (CALL_P (insn))
     200              :         return false;
     201              : 
     202     12973801 :       if (insn == BB_END (bb))
     203              :         break;
     204     12372298 :       insn = NEXT_INSN (insn);
     205     12372298 :     }
     206              : 
     207              :   return true;
     208              : }
     209              : 
     210              : /* Return the first non-jump active insn in the basic block.  */
     211              : 
     212              : static rtx_insn *
     213      1540542 : first_active_insn (basic_block bb)
     214              : {
     215      1540542 :   rtx_insn *insn = BB_HEAD (bb);
     216              : 
     217      1540542 :   if (LABEL_P (insn))
     218              :     {
     219       288674 :       if (insn == BB_END (bb))
     220              :         return NULL;
     221       288674 :       insn = NEXT_INSN (insn);
     222              :     }
     223              : 
     224      4856550 :   while (NOTE_P (insn) || DEBUG_INSN_P (insn))
     225              :     {
     226      3316008 :       if (insn == BB_END (bb))
     227              :         return NULL;
     228      3316008 :       insn = NEXT_INSN (insn);
     229              :     }
     230              : 
     231      1540542 :   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      2592923 : last_active_insn (basic_block bb, bool skip_use_p)
     241              : {
     242      2592923 :   rtx_insn *insn = BB_END (bb);
     243      2592923 :   rtx_insn *head = BB_HEAD (bb);
     244              : 
     245      2592923 :   while (NOTE_P (insn)
     246              :          || JUMP_P (insn)
     247              :          || DEBUG_INSN_P (insn)
     248      6157437 :          || (skip_use_p
     249            0 :              && NONJUMP_INSN_P (insn)
     250            0 :              && GET_CODE (PATTERN (insn)) == USE))
     251              :     {
     252      3564694 :       if (insn == head)
     253              :         return NULL;
     254      3564514 :       insn = PREV_INSN (insn);
     255              :     }
     256              : 
     257      2592743 :   if (LABEL_P (insn))
     258           86 :     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       499645 : rtx_interchangeable_p (const_rtx a, const_rtx b)
     319              : {
     320       499645 :   if (!rtx_equal_p (a, b))
     321              :     return false;
     322              : 
     323       182508 :   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         2321 :   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       119684 : cond_exec_get_condition (rtx_insn *jump, bool get_reversed = false)
     440              : {
     441       119684 :   rtx test_if, cond;
     442              : 
     443       119684 :   if (any_condjump_p (jump))
     444       119684 :     test_if = SET_SRC (pc_set (jump));
     445              :   else
     446              :     return NULL_RTX;
     447       119684 :   cond = XEXP (test_if, 0);
     448              : 
     449              :   /* If this branches to JUMP_LABEL when the condition is false,
     450              :      reverse the condition.  */
     451       119684 :   if (get_reversed
     452       119684 :       || (GET_CODE (XEXP (test_if, 2)) == LABEL_REF
     453            0 :           && label_ref_label (XEXP (test_if, 2))
     454            0 :           == JUMP_LABEL (jump)))
     455              :     {
     456        59842 :       enum rtx_code rev = reversed_comparison_code (cond, jump);
     457        59842 :       if (rev == UNKNOWN)
     458              :         return NULL_RTX;
     459              : 
     460        59842 :       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            0 :       true_prob_val = profile_probability::uninitialized ();
     639            0 :       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       274681 : noce_reversed_cond_code (struct noce_if_info *if_info)
     799              : {
     800       274681 :   if (if_info->rev_cond)
     801       274681 :     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       167137 : default_noce_conversion_profitable_p (rtx_insn *seq,
     812              :                                       struct noce_if_info *if_info)
     813              : {
     814       167137 :   bool speed_p = if_info->speed_p;
     815              : 
     816              :   /* Cost up the new sequence.  */
     817       167137 :   unsigned int cost = seq_cost (seq, speed_p);
     818              : 
     819       167137 :   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        84936 :   return speed_p && cost <= if_info->max_seq_cost;
     825              : }
     826              : 
     827              : /* Helper function for noce_try_store_flag*.  */
     828              : 
     829              : static rtx
     830        55221 : noce_emit_store_flag (struct noce_if_info *if_info, rtx x, bool reversep,
     831              :                       int normalize)
     832              : {
     833        55221 :   rtx cond = if_info->cond;
     834        55221 :   bool cond_complex;
     835        55221 :   enum rtx_code code;
     836              : 
     837        55221 :   cond_complex = (! general_operand (XEXP (cond, 0), VOIDmode)
     838        55221 :                   || ! 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        55221 :   if (cond_complex)
     844              :     {
     845        23972 :       rtx set = pc_set (if_info->jump);
     846        23972 :       cond = XEXP (SET_SRC (set), 0);
     847        23972 :       if (GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
     848        23972 :           && label_ref_label (XEXP (SET_SRC (set), 2)) == JUMP_LABEL (if_info->jump))
     849            0 :         reversep = !reversep;
     850        23972 :       if (if_info->then_else_reversed)
     851        21500 :         reversep = !reversep;
     852              :     }
     853        31249 :   else if (reversep
     854        14494 :            && if_info->rev_cond
     855        14494 :            && general_operand (XEXP (if_info->rev_cond, 0), VOIDmode)
     856        45743 :            && general_operand (XEXP (if_info->rev_cond, 1), VOIDmode))
     857              :     {
     858        14494 :       cond = if_info->rev_cond;
     859        14494 :       reversep = false;
     860              :     }
     861              : 
     862        55221 :   if (reversep)
     863         4449 :     code = reversed_comparison_code (cond, if_info->jump);
     864              :   else
     865        50772 :     code = GET_CODE (cond);
     866              : 
     867        55221 :   if ((if_info->cond_earliest == if_info->jump || cond_complex)
     868        23972 :       && (normalize == 0 || STORE_FLAG_VALUE == normalize))
     869              :     {
     870        18363 :       rtx src = gen_rtx_fmt_ee (code, GET_MODE (x), XEXP (cond, 0),
     871              :                                 XEXP (cond, 1));
     872        18363 :       rtx set = gen_rtx_SET (x, src);
     873              : 
     874        18363 :       start_sequence ();
     875        18363 :       rtx_insn *insn = emit_insn (set);
     876              : 
     877        18363 :       if (recog_memoized (insn) >= 0)
     878              :         {
     879         8055 :           rtx_insn *seq = end_sequence ();
     880         8055 :           emit_insn (seq);
     881              : 
     882         8055 :           if_info->cond_earliest = if_info->jump;
     883              : 
     884         8055 :           return x;
     885              :         }
     886              : 
     887        10308 :       end_sequence ();
     888              :     }
     889              : 
     890              :   /* Don't even try if the comparison operands or the mode of X are weird.  */
     891        47166 :   if (cond_complex || !SCALAR_INT_MODE_P (GET_MODE (x)))
     892        15927 :     return NULL_RTX;
     893              : 
     894              :   /* Don't try if mode of X is more than the max fixed mode size.  */
     895        93717 :   if (known_le (MAX_FIXED_MODE_SIZE, GET_MODE_BITSIZE (GET_MODE (x))))
     896              :     return NULL_RTX;
     897              : 
     898        30390 :   return emit_store_flag (x, code, XEXP (cond, 0),
     899              :                           XEXP (cond, 1), VOIDmode,
     900        30390 :                           (code == LTU || code == LEU
     901        60780 :                            || 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      1743350 : noce_can_force_operand (rtx x)
     909              : {
     910      1743350 :   if (general_operand (x, VOIDmode))
     911              :     return true;
     912       376454 :   if (SUBREG_P (x))
     913              :     {
     914          374 :       if (!noce_can_force_operand (SUBREG_REG (x)))
     915              :         return false;
     916              :       return true;
     917              :     }
     918       376080 :   if (ARITHMETIC_P (x))
     919              :     {
     920       327927 :       if (!noce_can_force_operand (XEXP (x, 0))
     921       327927 :           || !noce_can_force_operand (XEXP (x, 1)))
     922         3985 :         return false;
     923       323942 :       switch (GET_CODE (x))
     924              :         {
     925              :         case MULT:
     926              :         case MOD:
     927              :         case UDIV:
     928              :         case UMOD:
     929              :           return true;
     930          455 :         case DIV:
     931          455 :           if (INTEGRAL_MODE_P (GET_MODE (x)))
     932              :             return true;
     933              :           /* FALLTHRU */
     934       316688 :         default:
     935       316688 :           auto optab = code_to_optab (GET_CODE (x));
     936       316688 :           if (!optab)
     937              :             return false;
     938       314385 :           return optab_handler (optab, GET_MODE (x));
     939              :         }
     940              :     }
     941        48153 :   if (UNARY_P (x))
     942              :     {
     943        41307 :       if (!noce_can_force_operand (XEXP (x, 0)))
     944              :         return false;
     945        41294 :       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         5424 :         default:
     958         5424 :           auto optab = code_to_optab (GET_CODE (x));
     959         5424 :           if (!optab)
     960              :             return false;
     961         5424 :           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       106979 : noce_emit_move_insn (rtx x, rtx y)
     972              : {
     973       106979 :   machine_mode outmode;
     974       106979 :   rtx outer, inner;
     975       106979 :   poly_int64 bitpos;
     976              : 
     977       106979 :   if (GET_CODE (x) != STRICT_LOW_PART)
     978              :     {
     979       106979 :       rtx_insn *seq, *insn;
     980       106979 :       rtx target;
     981       106979 :       optab ot;
     982              : 
     983       106979 :       start_sequence ();
     984              :       /* Check that the SET_SRC is reasonable before calling emit_move_insn,
     985              :          otherwise construct a suitable SET pattern ourselves.  */
     986       107059 :       insn = (OBJECT_P (y) || CONSTANT_P (y) || GET_CODE (y) == SUBREG)
     987       107059 :              ? emit_move_insn (x, y)
     988        85752 :              : emit_insn (gen_rtx_SET (x, y));
     989       106979 :       seq = end_sequence ();
     990              : 
     991       106979 :       if (recog_memoized (insn) <= 0)
     992              :         {
     993        51229 :           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        51229 :           switch (GET_RTX_CLASS (GET_CODE (y)))
    1022              :             {
    1023          820 :             case RTX_UNARY:
    1024          820 :               ot = code_to_optab (GET_CODE (y));
    1025          820 :               if (ot && noce_can_force_operand (XEXP (y, 0)))
    1026              :                 {
    1027          638 :                   start_sequence ();
    1028          638 :                   target = expand_unop (GET_MODE (y), ot, XEXP (y, 0), x, 0);
    1029          638 :                   if (target != NULL_RTX)
    1030              :                     {
    1031          638 :                       if (target != x)
    1032            0 :                         emit_move_insn (x, target);
    1033          638 :                       seq = get_insns ();
    1034              :                     }
    1035          638 :                   end_sequence ();
    1036              :                 }
    1037              :               break;
    1038              : 
    1039        19581 :             case RTX_BIN_ARITH:
    1040        19581 :             case RTX_COMM_ARITH:
    1041        19581 :               ot = code_to_optab (GET_CODE (y));
    1042        19581 :               if (ot
    1043        19581 :                   && noce_can_force_operand (XEXP (y, 0))
    1044        39162 :                   && noce_can_force_operand (XEXP (y, 1)))
    1045              :                 {
    1046        19581 :                   start_sequence ();
    1047        19581 :                   target = expand_binop (GET_MODE (y), ot,
    1048              :                                          XEXP (y, 0), XEXP (y, 1),
    1049              :                                          x, 0, OPTAB_DIRECT);
    1050        19581 :                   if (target != NULL_RTX)
    1051              :                     {
    1052        19553 :                       if (target != x)
    1053            0 :                           emit_move_insn (x, target);
    1054        19553 :                       seq = get_insns ();
    1055              :                     }
    1056        19581 :                   end_sequence ();
    1057              :                 }
    1058              :               break;
    1059              : 
    1060              :             default:
    1061              :               break;
    1062              :             }
    1063              :         }
    1064              : 
    1065       106979 :       emit_insn (seq);
    1066       106979 :       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      4169322 : cc_in_cond (rtx cond)
    1081              : {
    1082      4169322 :   if (have_cbranchcc4 && cond
    1083      4169322 :       && GET_MODE_CLASS (GET_MODE (XEXP (cond, 0))) == MODE_CC)
    1084       133065 :     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       222597 : end_ifcvt_sequence (struct noce_if_info *if_info)
    1096              : {
    1097       222597 :   rtx_insn *insn;
    1098       222597 :   rtx_insn *seq = get_insns ();
    1099       222597 :   rtx cc = cc_in_cond (if_info->cond);
    1100              : 
    1101       222597 :   set_used_flags (if_info->x);
    1102       222597 :   set_used_flags (if_info->cond);
    1103       222597 :   set_used_flags (if_info->a);
    1104       222597 :   set_used_flags (if_info->b);
    1105              : 
    1106      1139177 :   for (insn = seq; insn; insn = NEXT_INSN (insn))
    1107       693983 :     set_used_flags (insn);
    1108              : 
    1109       222597 :   unshare_all_rtl_in_chain (seq);
    1110       222597 :   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      1106724 :   for (insn = seq; insn; insn = NEXT_INSN (insn))
    1117       693459 :     if (JUMP_P (insn)
    1118       693459 :         || recog_memoized (insn) == -1
    1119              :            /* Make sure new generated code does not clobber CC.  */
    1120      1355064 :         || (cc && set_of (cc, insn)))
    1121        31929 :       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      2994163 : noce_simple_bbs (struct noce_if_info *if_info)
    1131              : {
    1132            0 :   if (!if_info->then_simple)
    1133              :     return false;
    1134              : 
    1135      2779372 :   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       251585 : noce_try_move (struct noce_if_info *if_info)
    1146              : {
    1147       251585 :   rtx cond = if_info->cond;
    1148       251585 :   enum rtx_code code = GET_CODE (cond);
    1149       251585 :   rtx y;
    1150       251585 :   rtx_insn *seq;
    1151              : 
    1152       251585 :   if (code != NE && code != EQ)
    1153              :     return false;
    1154              : 
    1155       502913 :   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       178099 :   if (HONOR_NANS (if_info->x)
    1161       178099 :       || HONOR_SIGNED_ZEROS (if_info->x))
    1162        26505 :     return false;
    1163              : 
    1164              :   /* Check whether the operands of the comparison are A and in
    1165              :      either order.  */
    1166       151594 :   if ((rtx_equal_p (if_info->a, XEXP (cond, 0))
    1167         2277 :        && rtx_equal_p (if_info->b, XEXP (cond, 1)))
    1168       153859 :       || (rtx_equal_p (if_info->a, XEXP (cond, 1))
    1169        15383 :           && rtx_equal_p (if_info->b, XEXP (cond, 0))))
    1170              :     {
    1171           21 :       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       206645 : noce_try_sign_bit_splat (struct noce_if_info *if_info)
    1203              : {
    1204       206645 :   rtx cond = if_info->cond;
    1205       206645 :   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       206645 :   if (((code == LT || code == GE)
    1210        10092 :        && XEXP (cond, 1) == CONST0_RTX (GET_MODE (cond)))
    1211       204379 :       || ((code == LE || code == GT)
    1212        11601 :           && 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       214277 :   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         6067 :   if (!CONST_INT_P (if_info->a)
    1226         1932 :       || !CONST_INT_P (if_info->b)
    1227          635 :       || !REG_P (if_info->x))
    1228              :     return false;
    1229              : 
    1230          635 :   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          635 :   if (mode != GET_MODE (XEXP (cond, 0)))
    1235              :     return false;
    1236              : 
    1237          205 :   HOST_WIDE_INT val_a = INTVAL (if_info->a);
    1238          205 :   HOST_WIDE_INT val_b = INTVAL (if_info->b);
    1239              : 
    1240          205 :   rtx_insn *seq;
    1241          205 :   start_sequence ();
    1242              : 
    1243              :   /* We're testing the sign bit of this operand.  */
    1244          205 :   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          205 :   int splat_count = GET_MODE_BITSIZE (GET_MODE (condop)).to_constant () - 1;
    1254          205 :   rtx splat = GEN_INT (splat_count);
    1255              : 
    1256          205 :   rtx temp;
    1257          205 :   temp = expand_simple_binop (GET_MODE (XEXP (cond, 0)), ASHIFTRT,
    1258              :                               XEXP (cond, 0), splat, NULL_RTX,
    1259              :                               false, OPTAB_WIDEN);
    1260          205 :   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          205 :   if (val_a == -1)
    1267              :     {
    1268           47 :       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           47 :       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          158 :   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 currently -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          158 :   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          112 :   else if (val_a == 0)
    1334              :     {
    1335           81 :       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 currently -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           81 :       rtx and_form = gen_rtx_AND (mode, temp, GEN_INT (val_b));
    1349           81 :       rtx shift_left = gen_rtx_ASHIFT (mode, temp, GEN_INT (ctz_hwi (val_b)));
    1350           81 :       HOST_WIDE_INT rshift_count
    1351           81 :         = (clz_hwi (val_b) & (GET_MODE_PRECISION (mode).to_constant() - 1));
    1352           81 :       rtx shift_right = gen_rtx_LSHIFTRT (mode, temp, GEN_INT (rshift_count));
    1353           81 :       bool speed_p = optimize_insn_for_speed_p ();
    1354           81 :       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           78 :       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           78 :         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          174 :   if (!temp)
    1375           31 :     goto fail;
    1376              : 
    1377              :   /* Move into the final destination if the value wasn't
    1378              :      constructed there.  */
    1379          174 :   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          174 :   seq = end_ifcvt_sequence (if_info);
    1384          174 :   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          174 :   emit_insn_before_setloc (seq, if_info->jump,
    1389          174 :                            INSN_LOCATION (if_info->insn_a));
    1390          174 :   if_info->transform_name = "splat_sign_bit_trivial";
    1391          174 :   return true;
    1392              : 
    1393           31 :  fail:
    1394           31 :   end_ifcvt_sequence (if_info);
    1395           31 :   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       251585 : noce_try_ifelse_collapse (struct noce_if_info * if_info)
    1405              : {
    1406       556312 :   if (!noce_simple_bbs (if_info))
    1407              :     return false;
    1408              : 
    1409       233991 :   machine_mode mode = GET_MODE (if_info->x);
    1410       233991 :   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       233991 :   if (GET_CODE (if_then_else) == IF_THEN_ELSE)
    1415              :     return false;
    1416              : 
    1417        46509 :   rtx_insn *seq;
    1418        46509 :   start_sequence ();
    1419        46509 :   noce_emit_move_insn (if_info->x, if_then_else);
    1420        46509 :   seq = end_ifcvt_sequence (if_info);
    1421        46509 :   if (!seq)
    1422              :     return false;
    1423              : 
    1424        15681 :   emit_insn_before_setloc (seq, if_info->jump,
    1425        15681 :                           INSN_LOCATION (if_info->insn_a));
    1426              : 
    1427        15681 :   if_info->transform_name = "noce_try_ifelse_collapse";
    1428        15681 :   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       235904 : noce_try_store_flag (struct noce_if_info *if_info)
    1440              : {
    1441       235904 :   bool reversep;
    1442       235904 :   rtx target;
    1443       235904 :   rtx_insn *seq;
    1444              : 
    1445       501331 :   if (!noce_simple_bbs (if_info))
    1446              :     return false;
    1447              : 
    1448       218310 :   if (CONST_INT_P (if_info->b)
    1449        74846 :       && INTVAL (if_info->b) == STORE_FLAG_VALUE
    1450        13285 :       && if_info->a == const0_rtx)
    1451              :     reversep = false;
    1452       207891 :   else if (if_info->b == const0_rtx
    1453        30538 :            && CONST_INT_P (if_info->a)
    1454        20863 :            && INTVAL (if_info->a) == STORE_FLAG_VALUE
    1455       228301 :            && noce_reversed_cond_code (if_info) != UNKNOWN)
    1456              :     reversep = true;
    1457              :   else
    1458       187481 :     return false;
    1459              : 
    1460        30829 :   start_sequence ();
    1461              : 
    1462        30829 :   target = noce_emit_store_flag (if_info, if_info->x, reversep, 0);
    1463        30829 :   if (target)
    1464              :     {
    1465        26017 :       if (target != if_info->x)
    1466         2995 :         noce_emit_move_insn (if_info->x, target);
    1467              : 
    1468        26017 :       seq = end_ifcvt_sequence (if_info);
    1469        26017 :       if (! seq)
    1470              :         return false;
    1471              : 
    1472        26017 :       emit_insn_before_setloc (seq, if_info->jump,
    1473        26017 :                                INSN_LOCATION (if_info->insn_a));
    1474        26017 :       if_info->transform_name = "noce_try_store_flag";
    1475        26017 :       return true;
    1476              :     }
    1477              :   else
    1478              :     {
    1479         4812 :       end_sequence ();
    1480         4812 :       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       209811 : noce_try_inverse_constants (struct noce_if_info *if_info)
    1496              : {
    1497       465538 :   if (!noce_simple_bbs (if_info))
    1498              :     return false;
    1499              : 
    1500       192217 :   if (!CONST_INT_P (if_info->a)
    1501        51048 :       || !CONST_INT_P (if_info->b)
    1502        21398 :       || !REG_P (if_info->x))
    1503              :     return false;
    1504              : 
    1505        21398 :   machine_mode mode = GET_MODE (if_info->x);
    1506              : 
    1507        21398 :   HOST_WIDE_INT val_a = INTVAL (if_info->a);
    1508        21398 :   HOST_WIDE_INT val_b = INTVAL (if_info->b);
    1509              : 
    1510        21398 :   rtx cond = if_info->cond;
    1511              : 
    1512        21398 :   rtx x = if_info->x;
    1513        21398 :   rtx target;
    1514              : 
    1515        21398 :   start_sequence ();
    1516              : 
    1517        21398 :   rtx_code code;
    1518        21398 :   if (val_b != HOST_WIDE_INT_MIN && val_a == -val_b)
    1519              :     code = NEG;
    1520        20151 :   else if (val_a == ~val_b)
    1521              :     code = NOT;
    1522              :   else
    1523              :     {
    1524        20083 :       end_sequence ();
    1525        20083 :       return false;
    1526              :     }
    1527              : 
    1528         1315 :   rtx tmp = gen_reg_rtx (mode);
    1529         1315 :   noce_emit_move_insn (tmp, if_info->a);
    1530              : 
    1531         1315 :   target = emit_conditional_neg_or_complement (x, code, mode, cond, tmp, tmp);
    1532              : 
    1533         1315 :   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         1315 :   end_sequence ();
    1558         1315 :   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       209811 : noce_try_store_flag_constants (struct noce_if_info *if_info)
    1568              : {
    1569       209811 :   rtx target;
    1570       209811 :   rtx_insn *seq;
    1571       209811 :   bool reversep;
    1572       209811 :   HOST_WIDE_INT itrue, ifalse, diff, tmp;
    1573       209811 :   int normalize;
    1574       209811 :   bool can_reverse;
    1575       209811 :   machine_mode mode = GET_MODE (if_info->x);
    1576       209811 :   rtx common = NULL_RTX;
    1577              : 
    1578       209811 :   rtx a = if_info->a;
    1579       209811 :   rtx b = if_info->b;
    1580              : 
    1581              :   /* Handle cases like x := test ? y + 3 : y + 4.  */
    1582       209811 :   if (GET_CODE (a) == PLUS
    1583        22784 :       && GET_CODE (b) == PLUS
    1584         1488 :       && CONST_INT_P (XEXP (a, 1))
    1585          586 :       && CONST_INT_P (XEXP (b, 1))
    1586          504 :       && 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       210254 :       && (REG_P (XEXP (a, 0))
    1590            6 :           || (noce_operand_ok (XEXP (a, 0))
    1591            6 :               && ! reg_overlap_mentioned_p (if_info->x, XEXP (a, 0)))))
    1592              :     {
    1593          443 :       common = XEXP (a, 0);
    1594          443 :       a = XEXP (a, 1);
    1595          443 :       b = XEXP (b, 1);
    1596              :     }
    1597              : 
    1598       273321 :   if (!noce_simple_bbs (if_info))
    1599              :     return false;
    1600              : 
    1601       192217 :   if (CONST_INT_P (a)
    1602        51479 :       && CONST_INT_P (b))
    1603              :     {
    1604        21829 :       ifalse = INTVAL (a);
    1605        21829 :       itrue = INTVAL (b);
    1606        21829 :       bool subtract_flag_p = false;
    1607              : 
    1608        21829 :       diff = (unsigned HOST_WIDE_INT) itrue - ifalse;
    1609              :       /* Make sure we can represent the difference between the two values.  */
    1610        21829 :       if ((diff > 0)
    1611        21829 :           != ((ifalse < 0) != (itrue < 0) ? ifalse < 0 : ifalse < itrue))
    1612              :         return false;
    1613              : 
    1614        21727 :       diff = trunc_int_for_mode (diff, mode);
    1615              : 
    1616        21727 :       can_reverse = noce_reversed_cond_code (if_info) != UNKNOWN;
    1617        21727 :       reversep = false;
    1618        21727 :       if (diff == STORE_FLAG_VALUE || diff == -STORE_FLAG_VALUE)
    1619              :         {
    1620        11998 :           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        11998 :           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        11998 :           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        11998 :           else if (diff < 0 && STORE_FLAG_VALUE > 0)
    1646              :             {
    1647         6156 :               reversep = can_reverse;
    1648         6156 :               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         6156 :               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          514 :       else if (ifalse == 0 && pow2p_hwi (itrue)
    1664         9729 :                && STORE_FLAG_VALUE == 1)
    1665              :         normalize = 1;
    1666              :       /* Is this (cond) ? 0 : 2^n?  */
    1667       207031 :       else if (itrue == 0 && pow2p_hwi (ifalse) && can_reverse
    1668         9723 :                && 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         6156 :       if (reversep)
    1688              :         {
    1689         6157 :           std::swap (itrue, ifalse);
    1690         6157 :           diff = trunc_int_for_mode (-(unsigned HOST_WIDE_INT) diff, mode);
    1691              :         }
    1692              : 
    1693        12006 :       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        12006 :       if (common && rtx_equal_p (common, if_info->x))
    1698              :         {
    1699            5 :           common = gen_reg_rtx (mode);
    1700            5 :           noce_emit_move_insn (common, if_info->x);
    1701              :         }
    1702              : 
    1703        12006 :       target = noce_emit_store_flag (if_info, if_info->x, reversep, normalize);
    1704        12006 :       if (! target)
    1705              :         {
    1706         4848 :           end_sequence ();
    1707         4848 :           return false;
    1708              :         }
    1709              : 
    1710              :       /* if (test) x = 3; else x = 4;
    1711              :          =>   x = 3 + (test == 0);  */
    1712         7158 :       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         7150 :           if (common)
    1718           28 :             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        14300 :           target = expand_simple_binop (mode, subtract_flag_p ? MINUS : PLUS,
    1725         7150 :                                         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            8 :       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            8 :       else if (ifalse == 0 && (tmp = exact_log2 (itrue)) >= 0)
    1738              :         {
    1739            8 :           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         7158 :       if (! target)
    1759              :         {
    1760            0 :           end_sequence ();
    1761            0 :           return false;
    1762              :         }
    1763              : 
    1764         7158 :       if (target != if_info->x)
    1765            0 :         noce_emit_move_insn (if_info->x, target);
    1766              : 
    1767         7158 :       seq = end_ifcvt_sequence (if_info);
    1768         7158 :       if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
    1769         3992 :         return false;
    1770              : 
    1771         3166 :       emit_insn_before_setloc (seq, if_info->jump,
    1772         3166 :                                INSN_LOCATION (if_info->insn_a));
    1773         3166 :       if_info->transform_name = "noce_try_store_flag_constants";
    1774              : 
    1775         3166 :       return true;
    1776              :     }
    1777              : 
    1778              :   return false;
    1779              : }
    1780              : 
    1781              : /* This is trying to capture cases like dest = cond ? a : -1.
    1782              : 
    1783              :    The basic idea is to use a store-flag insn to generate a -1/0
    1784              :    value (directly or indirectly), then IOR that with the other
    1785              :    input.  */
    1786              : static bool
    1787       206471 : noce_try_store_flag_logical (struct noce_if_info *if_info)
    1788              : {
    1789       206471 :   rtx a = if_info->a;
    1790       206471 :   rtx b = if_info->b;
    1791       206471 :   rtx dest = if_info->x;
    1792       206471 :   machine_mode mode = GET_MODE (dest);
    1793              : 
    1794       206471 :   if (STORE_FLAG_VALUE != -1 && STORE_FLAG_VALUE != 1)
    1795              :     return false;
    1796              : 
    1797       455592 :   if (!noce_simple_bbs (if_info))
    1798              :     return false;
    1799              : 
    1800       188877 :   bool swapped = STORE_FLAG_VALUE == -1;
    1801       188877 :   if (a == CONSTM1_RTX (GET_MODE (dest))
    1802         1619 :       && if_info->rev_cond)
    1803              :     {
    1804              :       std::swap (a, b);
    1805       188877 :       swapped = !swapped;
    1806              :     }
    1807              : 
    1808       188877 :   if (b != CONSTM1_RTX (GET_MODE (dest)))
    1809              :     return false;
    1810              : 
    1811              :   /* If the other arm is not a REG/SUBREG, then punt.  This is primarily to
    1812              :      let the target handle the constant case, which it can likely do better.
    1813              :      It also means we don't have to worry about non terminal expressions.  */
    1814         2559 :   if (!REG_P (a) && !SUBREG_P (a))
    1815              :     return false;
    1816              : 
    1817              :   /* At this point we've got dest = cond ? a : -1.  Emit the store flag and
    1818              :      adjust its value (if necessary) to -1/0.  */
    1819          975 :   start_sequence ();
    1820          975 :   rtx temp = gen_reg_rtx (mode);
    1821          975 :   rtx target = noce_emit_store_flag (if_info, temp, !swapped, false);
    1822          975 :   if (!target)
    1823              :     {
    1824           88 :       end_sequence ();
    1825           88 :       return false;
    1826              :     }
    1827              : 
    1828          887 :   if (STORE_FLAG_VALUE == 1)
    1829              :     {
    1830          887 :       rtx x = gen_rtx_PLUS (mode, target, CONSTM1_RTX (mode));
    1831          887 :       emit_move_insn (target, x);
    1832              :     }
    1833              : 
    1834              :   /* Now we've got -1/0 in TARGET.  We can just IOR with A.  */
    1835          887 :   rtx x = gen_rtx_IOR (mode, target, a);
    1836          887 :   emit_move_insn (dest, x);
    1837              : 
    1838              :   /* We've generated all the RTL, make sure it recognizes and is
    1839              :      profitable.  */
    1840          887 :   rtx_insn *seq = end_ifcvt_sequence (if_info);
    1841          887 :   if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
    1842          887 :     return false;
    1843              : 
    1844            0 :   emit_insn_before_setloc (seq, if_info->jump,
    1845            0 :                            INSN_LOCATION (if_info->insn_a));
    1846            0 :   if_info->transform_name = "noce_try_store_flag_logical";
    1847            0 :   return true;
    1848              : }
    1849              : 
    1850              : /* Convert "if (test) foo++" into "foo += (test != 0)", and
    1851              :    similarly for "foo--".  */
    1852              : 
    1853              : static bool
    1854       164594 : noce_try_addcc (struct noce_if_info *if_info)
    1855              : {
    1856       164594 :   rtx target;
    1857       164594 :   rtx_insn *seq;
    1858       164594 :   bool subtract;
    1859       164594 :   int normalize;
    1860              : 
    1861       350214 :   if (!noce_simple_bbs (if_info))
    1862              :     return false;
    1863              : 
    1864       147000 :   if (GET_CODE (if_info->a) == PLUS
    1865        19961 :       && rtx_equal_p (XEXP (if_info->a, 0), if_info->b)
    1866       163475 :       && noce_reversed_cond_code (if_info) != UNKNOWN)
    1867              :     {
    1868        16475 :       rtx cond = if_info->rev_cond;
    1869        16475 :       enum rtx_code code;
    1870              : 
    1871        16475 :       if (cond == NULL_RTX)
    1872              :         {
    1873            0 :           cond = if_info->cond;
    1874            0 :           code = reversed_comparison_code (cond, if_info->jump);
    1875              :         }
    1876              :       else
    1877        16475 :         code = GET_CODE (cond);
    1878              : 
    1879              :       /* First try to use addcc pattern.  */
    1880        16475 :       if (general_operand (XEXP (cond, 0), VOIDmode)
    1881        16475 :           && general_operand (XEXP (cond, 1), VOIDmode))
    1882              :         {
    1883        14956 :           start_sequence ();
    1884        44868 :           target = emit_conditional_add (if_info->x, code,
    1885              :                                          XEXP (cond, 0),
    1886              :                                          XEXP (cond, 1),
    1887              :                                          VOIDmode,
    1888              :                                          if_info->b,
    1889        14956 :                                          XEXP (if_info->a, 1),
    1890        14956 :                                          GET_MODE (if_info->x),
    1891        14956 :                                          (code == LTU || code == GEU
    1892        14956 :                                           || code == LEU || code == GTU));
    1893        14956 :           if (target)
    1894              :             {
    1895         1281 :               if (target != if_info->x)
    1896            0 :                 noce_emit_move_insn (if_info->x, target);
    1897              : 
    1898         1281 :               seq = end_ifcvt_sequence (if_info);
    1899         1281 :               if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
    1900            0 :                 return false;
    1901              : 
    1902         1281 :               emit_insn_before_setloc (seq, if_info->jump,
    1903         1281 :                                        INSN_LOCATION (if_info->insn_a));
    1904         1281 :               if_info->transform_name = "noce_try_addcc";
    1905              : 
    1906         1281 :               return true;
    1907              :             }
    1908        13675 :           end_sequence ();
    1909              :         }
    1910              : 
    1911              :       /* If that fails, construct conditional increment or decrement using
    1912              :          setcc.  We're changing a branch and an increment to a comparison and
    1913              :          an ADD/SUB.  */
    1914        15194 :       if (XEXP (if_info->a, 1) == const1_rtx
    1915        10684 :           || XEXP (if_info->a, 1) == constm1_rtx)
    1916              :         {
    1917         5055 :           start_sequence ();
    1918         5055 :           if (STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1)))
    1919              :             subtract = false, normalize = 0;
    1920          545 :           else if (-STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1)))
    1921              :             subtract = true, normalize = 0;
    1922              :           else
    1923            0 :             subtract = false, normalize = INTVAL (XEXP (if_info->a, 1));
    1924              : 
    1925              : 
    1926         5055 :           target = noce_emit_store_flag (if_info,
    1927         5055 :                                          gen_reg_rtx (GET_MODE (if_info->x)),
    1928              :                                          true, normalize);
    1929              : 
    1930         5055 :           if (target)
    1931         7511 :             target = expand_simple_binop (GET_MODE (if_info->x),
    1932              :                                           subtract ? MINUS : PLUS,
    1933              :                                           if_info->b, target, if_info->x,
    1934              :                                           0, OPTAB_WIDEN);
    1935         4018 :           if (target)
    1936              :             {
    1937         4018 :               if (target != if_info->x)
    1938            0 :                 noce_emit_move_insn (if_info->x, target);
    1939              : 
    1940         4018 :               seq = end_ifcvt_sequence (if_info);
    1941         4018 :               if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
    1942          259 :                 return false;
    1943              : 
    1944         3759 :               emit_insn_before_setloc (seq, if_info->jump,
    1945         3759 :                                        INSN_LOCATION (if_info->insn_a));
    1946         3759 :               if_info->transform_name = "noce_try_addcc";
    1947         3759 :               return true;
    1948              :             }
    1949         1037 :           end_sequence ();
    1950              :         }
    1951              :     }
    1952              : 
    1953              :   return false;
    1954              : }
    1955              : 
    1956              : /* Convert "if (test) x = 0;" to "x &= -(test == 0);"  */
    1957              : 
    1958              : static bool
    1959       159554 : noce_try_store_flag_mask (struct noce_if_info *if_info)
    1960              : {
    1961       159554 :   rtx target;
    1962       159554 :   rtx_insn *seq;
    1963       159554 :   bool reversep;
    1964              : 
    1965       345073 :   if (!noce_simple_bbs (if_info))
    1966              :     return false;
    1967              : 
    1968       141960 :   reversep = false;
    1969              : 
    1970       141960 :   if ((if_info->a == const0_rtx
    1971         2493 :        && (REG_P (if_info->b) || rtx_equal_p (if_info->b, if_info->x)))
    1972       143374 :       || ((reversep = (noce_reversed_cond_code (if_info) != UNKNOWN))
    1973       140881 :           && if_info->b == const0_rtx
    1974        13220 :           && (REG_P (if_info->a) || rtx_equal_p (if_info->a, if_info->x))))
    1975              :     {
    1976         1081 :       start_sequence ();
    1977         1081 :       target = noce_emit_store_flag (if_info,
    1978         1081 :                                      gen_reg_rtx (GET_MODE (if_info->x)),
    1979              :                                      reversep, -1);
    1980         1081 :       if (target)
    1981          305 :         target = expand_simple_binop (GET_MODE (if_info->x), AND,
    1982              :                                       reversep ? if_info->a : if_info->b,
    1983              :                                       target, if_info->x, 0,
    1984              :                                       OPTAB_WIDEN);
    1985              : 
    1986          305 :       if (target)
    1987              :         {
    1988          305 :           if (target != if_info->x)
    1989            0 :             noce_emit_move_insn (if_info->x, target);
    1990              : 
    1991          305 :           seq = end_ifcvt_sequence (if_info);
    1992          305 :           if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
    1993          294 :             return false;
    1994              : 
    1995           11 :           emit_insn_before_setloc (seq, if_info->jump,
    1996           11 :                                    INSN_LOCATION (if_info->insn_a));
    1997           11 :           if_info->transform_name = "noce_try_store_flag_mask";
    1998              : 
    1999           11 :           return true;
    2000              :         }
    2001              : 
    2002          776 :       end_sequence ();
    2003              :     }
    2004              : 
    2005              :   return false;
    2006              : }
    2007              : 
    2008              : /* Helper function for noce_try_cmove and noce_try_cmove_arith.  */
    2009              : 
    2010              : static rtx
    2011       419418 : noce_emit_cmove (struct noce_if_info *if_info, rtx x, enum rtx_code code,
    2012              :                  rtx cmp_a, rtx cmp_b, rtx vfalse, rtx vtrue, rtx cc_cmp,
    2013              :                  rtx rev_cc_cmp)
    2014              : {
    2015       419418 :   rtx target ATTRIBUTE_UNUSED;
    2016       419418 :   bool unsignedp ATTRIBUTE_UNUSED;
    2017              : 
    2018              :   /* If earliest == jump, try to build the cmove insn directly.
    2019              :      This is helpful when combine has created some complex condition
    2020              :      (like for alpha's cmovlbs) that we can't hope to regenerate
    2021              :      through the normal interface.  */
    2022              : 
    2023       419418 :   if (if_info->cond_earliest == if_info->jump)
    2024              :     {
    2025         4402 :       rtx cond = gen_rtx_fmt_ee (code, GET_MODE (if_info->cond), cmp_a, cmp_b);
    2026         4402 :       rtx if_then_else = gen_rtx_IF_THEN_ELSE (GET_MODE (x),
    2027              :                                                cond, vtrue, vfalse);
    2028         4402 :       rtx set = gen_rtx_SET (x, if_then_else);
    2029              : 
    2030         4402 :       start_sequence ();
    2031         4402 :       rtx_insn *insn = emit_insn (set);
    2032              : 
    2033         4402 :       if (recog_memoized (insn) >= 0)
    2034              :         {
    2035         1350 :           rtx_insn *seq = end_sequence ();
    2036         1350 :           emit_insn (seq);
    2037              : 
    2038         1350 :           return x;
    2039              :         }
    2040              : 
    2041         3052 :       end_sequence ();
    2042              :     }
    2043              : 
    2044       836136 :   unsignedp = (code == LTU || code == GEU
    2045       418068 :                || code == LEU || code == GTU);
    2046              : 
    2047       418068 :   if (cc_cmp != NULL_RTX && rev_cc_cmp != NULL_RTX)
    2048        86824 :     target = emit_conditional_move (x, cc_cmp, rev_cc_cmp,
    2049        86824 :                                     vtrue, vfalse, GET_MODE (x));
    2050              :   else
    2051              :     {
    2052              :       /* Don't even try if the comparison operands are weird
    2053              :          except that the target supports cbranchcc4.  */
    2054       331244 :       if (! general_operand (cmp_a, GET_MODE (cmp_a))
    2055       331244 :           || ! general_operand (cmp_b, GET_MODE (cmp_b)))
    2056              :         {
    2057        24816 :           if (!have_cbranchcc4
    2058        24816 :               || GET_MODE_CLASS (GET_MODE (cmp_a)) != MODE_CC
    2059         2793 :               || cmp_b != const0_rtx)
    2060              :             return NULL_RTX;
    2061              :         }
    2062              : 
    2063       309221 :       target = emit_conditional_move (x, { code, cmp_a, cmp_b, VOIDmode },
    2064       309221 :                                       vtrue, vfalse, GET_MODE (x),
    2065              :                                       unsignedp);
    2066              :     }
    2067              : 
    2068       396045 :   if (target)
    2069              :     return target;
    2070              : 
    2071              :   /* We might be faced with a situation like:
    2072              : 
    2073              :      x = (reg:M TARGET)
    2074              :      vtrue = (subreg:M (reg:N VTRUE) BYTE)
    2075              :      vfalse = (subreg:M (reg:N VFALSE) BYTE)
    2076              : 
    2077              :      We can't do a conditional move in mode M, but it's possible that we
    2078              :      could do a conditional move in mode N instead and take a subreg of
    2079              :      the result.
    2080              : 
    2081              :      If we can't create new pseudos, though, don't bother.  */
    2082        42909 :   if (reload_completed)
    2083              :     return NULL_RTX;
    2084              : 
    2085        42909 :   if (GET_CODE (vtrue) == SUBREG && GET_CODE (vfalse) == SUBREG)
    2086              :     {
    2087           24 :       rtx reg_vtrue = SUBREG_REG (vtrue);
    2088           24 :       rtx reg_vfalse = SUBREG_REG (vfalse);
    2089           24 :       poly_uint64 byte_vtrue = SUBREG_BYTE (vtrue);
    2090           24 :       poly_uint64 byte_vfalse = SUBREG_BYTE (vfalse);
    2091           24 :       rtx promoted_target;
    2092              : 
    2093           24 :       if (GET_MODE (reg_vtrue) != GET_MODE (reg_vfalse)
    2094           24 :           || maybe_ne (byte_vtrue, byte_vfalse)
    2095           24 :           || (SUBREG_PROMOTED_VAR_P (vtrue)
    2096           24 :               != SUBREG_PROMOTED_VAR_P (vfalse))
    2097           24 :           || (SUBREG_PROMOTED_GET (vtrue)
    2098           24 :               != SUBREG_PROMOTED_GET (vfalse)))
    2099              :         return NULL_RTX;
    2100              : 
    2101           24 :       promoted_target = gen_reg_rtx (GET_MODE (reg_vtrue));
    2102              : 
    2103           48 :       target = emit_conditional_move (promoted_target,
    2104              :                                       { code, cmp_a, cmp_b, VOIDmode },
    2105              :                                       reg_vtrue, reg_vfalse,
    2106           24 :                                       GET_MODE (reg_vtrue), unsignedp);
    2107              :       /* Nope, couldn't do it in that mode either.  */
    2108           24 :       if (!target)
    2109              :         return NULL_RTX;
    2110              : 
    2111            6 :       target = gen_rtx_SUBREG (GET_MODE (vtrue), promoted_target, byte_vtrue);
    2112            6 :       SUBREG_PROMOTED_VAR_P (target) = SUBREG_PROMOTED_VAR_P (vtrue);
    2113            6 :       SUBREG_PROMOTED_SET (target, SUBREG_PROMOTED_GET (vtrue));
    2114            6 :       emit_move_insn (x, target);
    2115            6 :       return x;
    2116              :     }
    2117              :   else
    2118              :     return NULL_RTX;
    2119              : }
    2120              : 
    2121              : /* Try only simple constants and registers here.  More complex cases
    2122              :    are handled in noce_try_cmove_arith after noce_try_store_flag_arith
    2123              :    has had a go at it.  */
    2124              : 
    2125              : static bool
    2126       206471 : noce_try_cmove (struct noce_if_info *if_info)
    2127              : {
    2128       206471 :   enum rtx_code code;
    2129       206471 :   rtx target;
    2130       206471 :   rtx_insn *seq;
    2131              : 
    2132       413715 :   if (!noce_simple_bbs (if_info))
    2133              :     return false;
    2134              : 
    2135       131309 :   if ((CONSTANT_P (if_info->a) || register_operand (if_info->a, VOIDmode))
    2136       219918 :       && (CONSTANT_P (if_info->b) || register_operand (if_info->b, VOIDmode)))
    2137              :     {
    2138        81935 :       start_sequence ();
    2139              : 
    2140        81935 :       code = GET_CODE (if_info->cond);
    2141        81935 :       target = noce_emit_cmove (if_info, if_info->x, code,
    2142              :                                 XEXP (if_info->cond, 0),
    2143              :                                 XEXP (if_info->cond, 1),
    2144              :                                 if_info->a, if_info->b);
    2145              : 
    2146        81935 :       if (target)
    2147              :         {
    2148        55850 :           if (target != if_info->x)
    2149            0 :             noce_emit_move_insn (if_info->x, target);
    2150              : 
    2151        55850 :           seq = end_ifcvt_sequence (if_info);
    2152        55850 :           if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
    2153        14009 :             return false;
    2154              : 
    2155        41841 :           emit_insn_before_setloc (seq, if_info->jump,
    2156        41841 :                                    INSN_LOCATION (if_info->insn_a));
    2157        41841 :           if_info->transform_name = "noce_try_cmove";
    2158              : 
    2159        41841 :           return true;
    2160              :         }
    2161              :       /* If both a and b are constants try a last-ditch transformation:
    2162              :          if (test) x = a; else x = b;
    2163              :          =>   x = (-(test != 0) & (b - a)) + a;
    2164              :          Try this only if the target-specific expansion above has failed.
    2165              :          The target-specific expander may want to generate sequences that
    2166              :          we don't know about, so give them a chance before trying this
    2167              :          approach.  */
    2168        26085 :       else if (!targetm.have_conditional_execution ()
    2169        26085 :                 && CONST_INT_P (if_info->a) && CONST_INT_P (if_info->b))
    2170              :         {
    2171         5275 :           machine_mode mode = GET_MODE (if_info->x);
    2172         5275 :           HOST_WIDE_INT ifalse = INTVAL (if_info->a);
    2173         5275 :           HOST_WIDE_INT itrue = INTVAL (if_info->b);
    2174         5275 :           rtx target = noce_emit_store_flag (if_info, if_info->x, false, -1);
    2175         5275 :           if (!target)
    2176              :             {
    2177         5215 :               end_sequence ();
    2178         5215 :               return false;
    2179              :             }
    2180              : 
    2181           60 :           HOST_WIDE_INT diff = (unsigned HOST_WIDE_INT) itrue - ifalse;
    2182              :           /* Make sure we can represent the difference
    2183              :              between the two values.  */
    2184           60 :           if ((diff > 0)
    2185           60 :               != ((ifalse < 0) != (itrue < 0) ? ifalse < 0 : ifalse < itrue))
    2186              :             {
    2187           21 :               end_sequence ();
    2188           21 :               return false;
    2189              :             }
    2190              : 
    2191           39 :           diff = trunc_int_for_mode (diff, mode);
    2192           39 :           target = expand_simple_binop (mode, AND,
    2193           39 :                                         target, gen_int_mode (diff, mode),
    2194              :                                         if_info->x, 0, OPTAB_WIDEN);
    2195           39 :           if (target)
    2196           39 :             target = expand_simple_binop (mode, PLUS,
    2197           39 :                                           target, gen_int_mode (ifalse, mode),
    2198              :                                           if_info->x, 0, OPTAB_WIDEN);
    2199           39 :           if (target)
    2200              :             {
    2201           39 :               if (target != if_info->x)
    2202            0 :                 noce_emit_move_insn (if_info->x, target);
    2203              : 
    2204           39 :               seq = end_ifcvt_sequence (if_info);
    2205           39 :               if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
    2206            3 :                 return false;
    2207              : 
    2208           36 :               emit_insn_before_setloc (seq, if_info->jump,
    2209           36 :                                    INSN_LOCATION (if_info->insn_a));
    2210           36 :               if_info->transform_name = "noce_try_cmove";
    2211           36 :               return true;
    2212              :             }
    2213              :           else
    2214              :             {
    2215            0 :               end_sequence ();
    2216            0 :               return false;
    2217              :             }
    2218              :         }
    2219              :       else
    2220        20810 :         end_sequence ();
    2221              :     }
    2222              : 
    2223              :   return false;
    2224              : }
    2225              : 
    2226              : /* Return true if X contains a conditional code mode rtx.  */
    2227              : 
    2228              : static bool
    2229      2867843 : contains_ccmode_rtx_p (rtx x)
    2230              : {
    2231      2867843 :   subrtx_iterator::array_type array;
    2232      7321095 :   FOR_EACH_SUBRTX (iter, array, x, ALL)
    2233      4498096 :     if (GET_MODE_CLASS (GET_MODE (*iter)) == MODE_CC)
    2234        44844 :       return true;
    2235              : 
    2236      2822999 :   return false;
    2237      2867843 : }
    2238              : 
    2239              : /* Helper for bb_valid_for_noce_process_p.  Validate that
    2240              :    the rtx insn INSN is a single set that does not set
    2241              :    the conditional register CC and is in general valid for
    2242              :    if-conversion.  */
    2243              : 
    2244              : static bool
    2245      3610332 : insn_valid_noce_process_p (rtx_insn *insn, rtx cc)
    2246              : {
    2247      3610332 :   if (!insn
    2248      3610066 :       || !NONJUMP_INSN_P (insn)
    2249      6508933 :       || (cc && set_of (cc, insn)))
    2250       723024 :       return false;
    2251              : 
    2252      2887308 :   rtx sset = single_set (insn);
    2253              : 
    2254              :   /* Currently support only simple single sets in test_bb.  */
    2255      2887308 :   if (!sset
    2256      2881060 :       || !noce_operand_ok (SET_DEST (sset))
    2257      2867843 :       || contains_ccmode_rtx_p (SET_DEST (sset))
    2258      5710307 :       || !noce_operand_ok (SET_SRC (sset)))
    2259       127878 :     return false;
    2260              : 
    2261              :   return true;
    2262              : }
    2263              : 
    2264              : 
    2265              : /* Return true iff the registers that the insns in BB_A set do not get
    2266              :    used in BB_B.  If TO_RENAME is non-NULL then it is a location that will be
    2267              :    renamed later by the caller and so conflicts on it should be ignored
    2268              :    in this function.  */
    2269              : 
    2270              : static bool
    2271        54565 : bbs_ok_for_cmove_arith (basic_block bb_a, basic_block bb_b, rtx to_rename)
    2272              : {
    2273        54565 :   rtx_insn *a_insn;
    2274        54565 :   bitmap bba_sets = BITMAP_ALLOC (&reg_obstack);
    2275              : 
    2276        54565 :   df_ref def;
    2277        54565 :   df_ref use;
    2278              : 
    2279       273469 :   FOR_BB_INSNS (bb_a, a_insn)
    2280              :     {
    2281       218904 :       if (!active_insn_p (a_insn))
    2282       143316 :         continue;
    2283              : 
    2284        75588 :       rtx sset_a = single_set (a_insn);
    2285              : 
    2286        75588 :       if (!sset_a)
    2287              :         {
    2288            0 :           BITMAP_FREE (bba_sets);
    2289            0 :           return false;
    2290              :         }
    2291              :       /* Record all registers that BB_A sets.  */
    2292       184409 :       FOR_EACH_INSN_DEF (def, a_insn)
    2293       108821 :         if (!(to_rename && DF_REF_REG (def) == to_rename))
    2294        55246 :           bitmap_set_bit (bba_sets, DF_REF_REGNO (def));
    2295              :     }
    2296              : 
    2297        54565 :   rtx_insn *b_insn;
    2298              : 
    2299       273540 :   FOR_BB_INSNS (bb_b, b_insn)
    2300              :     {
    2301       219068 :       if (!active_insn_p (b_insn))
    2302       143487 :         continue;
    2303              : 
    2304        75581 :       rtx sset_b = single_set (b_insn);
    2305              : 
    2306        75581 :       if (!sset_b)
    2307              :         {
    2308            0 :           BITMAP_FREE (bba_sets);
    2309            0 :           return false;
    2310              :         }
    2311              : 
    2312              :       /* Make sure this is a REG and not some instance
    2313              :          of ZERO_EXTRACT or non-paradoxical SUBREG or other dangerous stuff.
    2314              :          If we have a memory destination then we have a pair of simple
    2315              :          basic blocks performing an operation of the form [addr] = c ? a : b.
    2316              :          bb_valid_for_noce_process_p will have ensured that these are
    2317              :          the only stores present.  In that case [addr] should be the location
    2318              :          to be renamed.  Assert that the callers set this up properly.  */
    2319        75581 :       if (MEM_P (SET_DEST (sset_b)))
    2320          982 :         gcc_assert (rtx_equal_p (SET_DEST (sset_b), to_rename));
    2321        74599 :       else if (!REG_P (SET_DEST (sset_b))
    2322        74599 :                && !paradoxical_subreg_p (SET_DEST (sset_b)))
    2323              :         {
    2324           36 :           BITMAP_FREE (bba_sets);
    2325           36 :           return false;
    2326              :         }
    2327              : 
    2328              :       /* If the insn uses a reg set in BB_A return false.  */
    2329       146918 :       FOR_EACH_INSN_USE (use, b_insn)
    2330              :         {
    2331        71430 :           if (bitmap_bit_p (bba_sets, DF_REF_REGNO (use)))
    2332              :             {
    2333           57 :               BITMAP_FREE (bba_sets);
    2334           57 :               return false;
    2335              :             }
    2336              :         }
    2337              : 
    2338              :     }
    2339              : 
    2340        54472 :   BITMAP_FREE (bba_sets);
    2341        54472 :   return true;
    2342              : }
    2343              : 
    2344              : /* Emit copies of all the active instructions in BB except the last.
    2345              :    This is a helper for noce_try_cmove_arith.  */
    2346              : 
    2347              : static void
    2348        13022 : noce_emit_all_but_last (basic_block bb)
    2349              : {
    2350        13022 :   rtx_insn *last = last_active_insn (bb, false);
    2351        13022 :   rtx_insn *insn;
    2352       138987 :   FOR_BB_INSNS (bb, insn)
    2353              :     {
    2354       112943 :       if (insn != last && active_insn_p (insn))
    2355              :         {
    2356        36436 :           rtx_insn *to_emit = as_a <rtx_insn *> (copy_rtx (insn));
    2357              : 
    2358        36436 :           emit_insn (PATTERN (to_emit));
    2359              :         }
    2360              :     }
    2361        13022 : }
    2362              : 
    2363              : /* Helper for noce_try_cmove_arith.  Emit the pattern TO_EMIT and return
    2364              :    the resulting insn or NULL if it's not a valid insn.  */
    2365              : 
    2366              : static rtx_insn *
    2367       147970 : noce_emit_insn (rtx to_emit)
    2368              : {
    2369       147970 :   gcc_assert (to_emit);
    2370       147970 :   rtx_insn *insn = emit_insn (to_emit);
    2371              : 
    2372       147970 :   if (recog_memoized (insn) < 0)
    2373          193 :     return NULL;
    2374              : 
    2375              :   return insn;
    2376              : }
    2377              : 
    2378              : /* Helper for noce_try_cmove_arith.  Emit a copy of the insns up to
    2379              :    and including the penultimate one in BB if it is not simple
    2380              :    (as indicated by SIMPLE).  Then emit LAST_INSN as the last
    2381              :    insn in the block.  The reason for that is that LAST_INSN may
    2382              :    have been modified by the preparation in noce_try_cmove_arith.  */
    2383              : 
    2384              : static bool
    2385       150190 : noce_emit_bb (rtx last_insn, basic_block bb, bool simple)
    2386              : {
    2387       150190 :   if (bb && !simple)
    2388        13022 :     noce_emit_all_but_last (bb);
    2389              : 
    2390       150190 :   if (last_insn && !noce_emit_insn (last_insn))
    2391              :     return false;
    2392              : 
    2393              :   return true;
    2394              : }
    2395              : 
    2396              : /* Try more complex cases involving conditional_move.  */
    2397              : 
    2398              : static bool
    2399       150982 : noce_try_cmove_arith (struct noce_if_info *if_info)
    2400              : {
    2401       150982 :   rtx a = if_info->a;
    2402       150982 :   rtx b = if_info->b;
    2403       150982 :   rtx x = if_info->x;
    2404       150982 :   rtx orig_a, orig_b;
    2405       150982 :   rtx_insn *insn_a, *insn_b;
    2406       150982 :   bool a_simple = if_info->then_simple;
    2407       150982 :   bool b_simple = if_info->else_simple;
    2408       150982 :   basic_block then_bb = if_info->then_bb;
    2409       150982 :   basic_block else_bb = if_info->else_bb;
    2410       150982 :   rtx target;
    2411       150982 :   bool is_mem = false;
    2412       150982 :   enum rtx_code code;
    2413       150982 :   rtx cond = if_info->cond;
    2414       150982 :   rtx_insn *ifcvt_seq;
    2415              : 
    2416              :   /* A conditional move from two memory sources is equivalent to a
    2417              :      conditional on their addresses followed by a load.  Don't do this
    2418              :      early because it'll screw alias analysis.  Note that we've
    2419              :      already checked for no side effects.  */
    2420       150982 :   if (cse_not_expected
    2421        48875 :       && MEM_P (a) && MEM_P (b)
    2422       153747 :       && MEM_ADDR_SPACE (a) == MEM_ADDR_SPACE (b))
    2423              :     {
    2424         2765 :       machine_mode address_mode = get_address_mode (a);
    2425              : 
    2426         2765 :       a = XEXP (a, 0);
    2427         2765 :       b = XEXP (b, 0);
    2428         2765 :       x = gen_reg_rtx (address_mode);
    2429         2765 :       is_mem = true;
    2430              :     }
    2431              : 
    2432              :   /* ??? We could handle this if we knew that a load from A or B could
    2433              :      not trap or fault.  This is also true if we've already loaded
    2434              :      from the address along the path from ENTRY.  */
    2435       148217 :   else if (may_trap_or_fault_p (a) || may_trap_or_fault_p (b))
    2436        55241 :     return false;
    2437              : 
    2438              :   /* if (test) x = a + b; else x = c - d;
    2439              :      => y = a + b;
    2440              :         x = c - d;
    2441              :         if (test)
    2442              :           x = y;
    2443              :   */
    2444              : 
    2445        95741 :   code = GET_CODE (cond);
    2446        95741 :   insn_a = if_info->insn_a;
    2447        95741 :   insn_b = if_info->insn_b;
    2448              : 
    2449        95741 :   machine_mode x_mode = GET_MODE (x);
    2450              : 
    2451        95741 :   if (!can_conditionally_move_p (x_mode))
    2452              :     return false;
    2453              : 
    2454              :   /* Possibly rearrange operands to make things come out more natural.  */
    2455        75188 :   if (noce_reversed_cond_code (if_info) != UNKNOWN)
    2456              :     {
    2457        75188 :       bool reversep = false;
    2458        75188 :       if (rtx_equal_p (b, x))
    2459              :         reversep = true;
    2460        46321 :       else if (general_operand (b, GET_MODE (b)))
    2461              :         reversep = true;
    2462              : 
    2463              :       if (reversep)
    2464              :         {
    2465        67806 :           if (if_info->rev_cond)
    2466              :             {
    2467        67806 :               cond = if_info->rev_cond;
    2468        67806 :               code = GET_CODE (cond);
    2469              :             }
    2470              :           else
    2471            0 :             code = reversed_comparison_code (cond, if_info->jump);
    2472              :           std::swap (a, b);
    2473              :           std::swap (insn_a, insn_b);
    2474              :           std::swap (a_simple, b_simple);
    2475              :           std::swap (then_bb, else_bb);
    2476              :         }
    2477              :     }
    2478              : 
    2479        28164 :   if (then_bb && else_bb
    2480       102517 :       && (!bbs_ok_for_cmove_arith (then_bb, else_bb,  if_info->orig_x)
    2481        27236 :           || !bbs_ok_for_cmove_arith (else_bb, then_bb,  if_info->orig_x)))
    2482           93 :     return false;
    2483              : 
    2484        75095 :   start_sequence ();
    2485              : 
    2486              :   /* If one of the blocks is empty then the corresponding B or A value
    2487              :      came from the test block.  The non-empty complex block that we will
    2488              :      emit might clobber the register used by B or A, so move it to a pseudo
    2489              :      first.  */
    2490              : 
    2491        75095 :   rtx tmp_a = NULL_RTX;
    2492        75095 :   rtx tmp_b = NULL_RTX;
    2493              : 
    2494        75095 :   if (b_simple || !else_bb)
    2495        64100 :     tmp_b = gen_reg_rtx (x_mode);
    2496              : 
    2497        75095 :   if (a_simple || !then_bb)
    2498        73068 :     tmp_a = gen_reg_rtx (x_mode);
    2499              : 
    2500        75095 :   orig_a = a;
    2501        75095 :   orig_b = b;
    2502              : 
    2503        75095 :   rtx emit_a = NULL_RTX;
    2504        75095 :   rtx emit_b = NULL_RTX;
    2505        75095 :   rtx_insn *tmp_insn = NULL;
    2506        75095 :   bool modified_in_a = false;
    2507        75095 :   bool modified_in_b = false;
    2508              :   /* If either operand is complex, load it into a register first.
    2509              :      The best way to do this is to copy the original insn.  In this
    2510              :      way we preserve any clobbers etc that the insn may have had.
    2511              :      This is of course not possible in the IS_MEM case.  */
    2512              : 
    2513        75095 :   if (! general_operand (a, GET_MODE (a)) || tmp_a)
    2514              :     {
    2515              : 
    2516        74508 :       if (is_mem)
    2517              :         {
    2518         2764 :           rtx reg = gen_reg_rtx (GET_MODE (a));
    2519         2764 :           emit_a = gen_rtx_SET (reg, a);
    2520              :         }
    2521              :       else
    2522              :         {
    2523        71744 :           if (insn_a)
    2524              :             {
    2525        42819 :               a = tmp_a ? tmp_a : gen_reg_rtx (GET_MODE (a));
    2526              : 
    2527        42819 :               rtx_insn *copy_of_a = as_a <rtx_insn *> (copy_rtx (insn_a));
    2528        42819 :               rtx set = single_set (copy_of_a);
    2529        42819 :               SET_DEST (set) = a;
    2530              : 
    2531        42819 :               emit_a = PATTERN (copy_of_a);
    2532              :             }
    2533              :           else
    2534              :             {
    2535        28925 :               rtx tmp_reg = tmp_a ? tmp_a : gen_reg_rtx (GET_MODE (a));
    2536        28925 :               emit_a = gen_rtx_SET (tmp_reg, a);
    2537        28925 :               a = tmp_reg;
    2538              :             }
    2539              :         }
    2540              :     }
    2541              : 
    2542        75095 :   if (! general_operand (b, GET_MODE (b)) || tmp_b)
    2543              :     {
    2544        73462 :       if (is_mem)
    2545              :         {
    2546         2764 :           rtx reg = gen_reg_rtx (GET_MODE (b));
    2547         2764 :           emit_b = gen_rtx_SET (reg, b);
    2548              :         }
    2549              :       else
    2550              :         {
    2551        70698 :           if (insn_b)
    2552              :             {
    2553        70507 :               b = tmp_b ? tmp_b : gen_reg_rtx (GET_MODE (b));
    2554        70507 :               rtx_insn *copy_of_b = as_a <rtx_insn *> (copy_rtx (insn_b));
    2555        70507 :               rtx set = single_set (copy_of_b);
    2556              : 
    2557        70507 :               SET_DEST (set) = b;
    2558        70507 :               emit_b = PATTERN (copy_of_b);
    2559              :             }
    2560              :           else
    2561              :             {
    2562          191 :               rtx tmp_reg = tmp_b ? tmp_b : gen_reg_rtx (GET_MODE (b));
    2563          191 :               emit_b = gen_rtx_SET (tmp_reg, b);
    2564          191 :               b = tmp_reg;
    2565              :             }
    2566              :         }
    2567              :     }
    2568              : 
    2569        75095 :   modified_in_a = emit_a != NULL_RTX && modified_in_p (orig_b, emit_a);
    2570        75095 :   if (tmp_b && then_bb)
    2571              :     {
    2572        80951 :       FOR_BB_INSNS (then_bb, tmp_insn)
    2573              :         /* Don't check inside insn_a.  We will have changed it to emit_a
    2574              :            with a destination that doesn't conflict.  */
    2575        61019 :         if (!(insn_a && tmp_insn == insn_a)
    2576       102106 :             && modified_in_p (orig_b, tmp_insn))
    2577              :           {
    2578              :             modified_in_a = true;
    2579              :             break;
    2580              :           }
    2581              : 
    2582              :     }
    2583              : 
    2584        75095 :   modified_in_b = emit_b != NULL_RTX && modified_in_p (orig_a, emit_b);
    2585        75095 :   if (tmp_a && else_bb)
    2586              :     {
    2587       337570 :       FOR_BB_INSNS (else_bb, tmp_insn)
    2588              :       /* Don't check inside insn_b.  We will have changed it to emit_b
    2589              :          with a destination that doesn't conflict.  */
    2590       265295 :       if (!(insn_b && tmp_insn == insn_b)
    2591       458315 :           && modified_in_p (orig_a, tmp_insn))
    2592              :         {
    2593              :           modified_in_b = true;
    2594              :           break;
    2595              :         }
    2596              :     }
    2597              : 
    2598              :   /* If insn to set up A clobbers any registers B depends on, try to
    2599              :      swap insn that sets up A with the one that sets up B.  If even
    2600              :      that doesn't help, punt.  */
    2601        75095 :   if (modified_in_a && !modified_in_b)
    2602              :     {
    2603            0 :       if (!noce_emit_bb (emit_b, else_bb, b_simple))
    2604            0 :         goto end_seq_and_fail;
    2605              : 
    2606            0 :       if (!noce_emit_bb (emit_a, then_bb, a_simple))
    2607            0 :         goto end_seq_and_fail;
    2608              :     }
    2609        75095 :   else if (!modified_in_a)
    2610              :     {
    2611        75095 :       if (!noce_emit_bb (emit_a, then_bb, a_simple))
    2612            0 :         goto end_seq_and_fail;
    2613              : 
    2614        75095 :       if (!noce_emit_bb (emit_b, else_bb, b_simple))
    2615          193 :         goto end_seq_and_fail;
    2616              :     }
    2617              :   else
    2618            0 :     goto end_seq_and_fail;
    2619              : 
    2620        74902 :   target = noce_emit_cmove (if_info, x, code, XEXP (cond, 0), XEXP (cond, 1),
    2621              :                             a, b);
    2622              : 
    2623        74902 :   if (! target)
    2624        18030 :     goto end_seq_and_fail;
    2625              : 
    2626              :   /* If we're handling a memory for above, emit the load now.  */
    2627        56872 :   if (is_mem)
    2628              :     {
    2629         2399 :       rtx mem = gen_rtx_MEM (GET_MODE (if_info->x), target);
    2630              : 
    2631              :       /* Copy over flags as appropriate.  */
    2632         2399 :       if (MEM_VOLATILE_P (if_info->a) || MEM_VOLATILE_P (if_info->b))
    2633            0 :         MEM_VOLATILE_P (mem) = 1;
    2634         2399 :       if (MEM_ALIAS_SET (if_info->a) == MEM_ALIAS_SET (if_info->b))
    2635         2219 :         set_mem_alias_set (mem, MEM_ALIAS_SET (if_info->a));
    2636         4798 :       set_mem_align (mem,
    2637         2399 :                      MIN (MEM_ALIGN (if_info->a), MEM_ALIGN (if_info->b)));
    2638              : 
    2639         2399 :       gcc_assert (MEM_ADDR_SPACE (if_info->a) == MEM_ADDR_SPACE (if_info->b));
    2640         2399 :       set_mem_addr_space (mem, MEM_ADDR_SPACE (if_info->a));
    2641              : 
    2642         2399 :       noce_emit_move_insn (if_info->x, mem);
    2643              :     }
    2644        54473 :   else if (target != x)
    2645            0 :     noce_emit_move_insn (x, target);
    2646              : 
    2647        56872 :   ifcvt_seq = end_ifcvt_sequence (if_info);
    2648        56872 :   if (!ifcvt_seq || !targetm.noce_conversion_profitable_p (ifcvt_seq, if_info))
    2649        18781 :     return false;
    2650              : 
    2651        38091 :   emit_insn_before_setloc (ifcvt_seq, if_info->jump,
    2652        38091 :                            INSN_LOCATION (if_info->insn_a));
    2653        38091 :   if_info->transform_name = "noce_try_cmove_arith";
    2654        38091 :   return true;
    2655              : 
    2656        18223 :  end_seq_and_fail:
    2657        18223 :   end_sequence ();
    2658        18223 :   return false;
    2659              : }
    2660              : 
    2661              : /* For most cases, the simplified condition we found is the best
    2662              :    choice, but this is not the case for the min/max/abs transforms.
    2663              :    For these we wish to know that it is A or B in the condition.  */
    2664              : 
    2665              : static rtx
    2666       162095 : noce_get_alt_condition (struct noce_if_info *if_info, rtx target,
    2667              :                         rtx_insn **earliest)
    2668              : {
    2669       162095 :   rtx cond, set;
    2670       162095 :   rtx_insn *insn;
    2671       162095 :   bool reverse;
    2672              : 
    2673              :   /* If target is already mentioned in the known condition, return it.  */
    2674       162095 :   if (reg_mentioned_p (target, if_info->cond))
    2675              :     {
    2676         7804 :       *earliest = if_info->cond_earliest;
    2677         7804 :       return if_info->cond;
    2678              :     }
    2679              : 
    2680       154291 :   set = pc_set (if_info->jump);
    2681       154291 :   cond = XEXP (SET_SRC (set), 0);
    2682       154291 :   reverse
    2683       308582 :     = GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
    2684       154291 :       && label_ref_label (XEXP (SET_SRC (set), 2)) == JUMP_LABEL (if_info->jump);
    2685       154291 :   if (if_info->then_else_reversed)
    2686        23711 :     reverse = !reverse;
    2687              : 
    2688              :   /* If we're looking for a constant, try to make the conditional
    2689              :      have that constant in it.  There are two reasons why it may
    2690              :      not have the constant we want:
    2691              : 
    2692              :      1. GCC may have needed to put the constant in a register, because
    2693              :         the target can't compare directly against that constant.  For
    2694              :         this case, we look for a SET immediately before the comparison
    2695              :         that puts a constant in that register.
    2696              : 
    2697              :      2. GCC may have canonicalized the conditional, for example
    2698              :         replacing "if x < 4" with "if x <= 3".  We can undo that (or
    2699              :         make equivalent types of changes) to get the constants we need
    2700              :         if they're off by one in the right direction.  */
    2701              : 
    2702       154291 :   if (CONST_INT_P (target))
    2703              :     {
    2704        46547 :       enum rtx_code code = GET_CODE (if_info->cond);
    2705        46547 :       rtx op_a = XEXP (if_info->cond, 0);
    2706        46547 :       rtx op_b = XEXP (if_info->cond, 1);
    2707        46547 :       rtx_insn *prev_insn;
    2708              : 
    2709              :       /* First, look to see if we put a constant in a register.  */
    2710        46547 :       prev_insn = prev_nonnote_nondebug_insn (if_info->cond_earliest);
    2711        46547 :       if (prev_insn
    2712        46437 :           && BLOCK_FOR_INSN (prev_insn)
    2713        46437 :              == BLOCK_FOR_INSN (if_info->cond_earliest)
    2714        37056 :           && INSN_P (prev_insn)
    2715        79617 :           && GET_CODE (PATTERN (prev_insn)) == SET)
    2716              :         {
    2717        25179 :           rtx src = find_reg_equal_equiv_note (prev_insn);
    2718        25179 :           if (!src)
    2719        25012 :             src = SET_SRC (PATTERN (prev_insn));
    2720        25179 :           if (CONST_INT_P (src))
    2721              :             {
    2722        15243 :               if (rtx_equal_p (op_a, SET_DEST (PATTERN (prev_insn))))
    2723              :                 op_a = src;
    2724        14724 :               else if (rtx_equal_p (op_b, SET_DEST (PATTERN (prev_insn))))
    2725         1073 :                 op_b = src;
    2726              : 
    2727        15243 :               if (CONST_INT_P (op_a))
    2728              :                 {
    2729          519 :                   std::swap (op_a, op_b);
    2730          519 :                   code = swap_condition (code);
    2731              :                 }
    2732              :             }
    2733              :         }
    2734              : 
    2735              :       /* Now, look to see if we can get the right constant by
    2736              :          adjusting the conditional.  */
    2737        46547 :       if (CONST_INT_P (op_b))
    2738              :         {
    2739        24033 :           HOST_WIDE_INT desired_val = INTVAL (target);
    2740        24033 :           HOST_WIDE_INT actual_val = INTVAL (op_b);
    2741              : 
    2742        24033 :           switch (code)
    2743              :             {
    2744         1121 :             case LT:
    2745         1121 :               if (desired_val != HOST_WIDE_INT_MAX
    2746         1106 :                   && actual_val == desired_val + 1)
    2747              :                 {
    2748          166 :                   code = LE;
    2749          166 :                   op_b = GEN_INT (desired_val);
    2750              :                 }
    2751              :               break;
    2752            3 :             case LE:
    2753            3 :               if (desired_val != HOST_WIDE_INT_MIN
    2754            3 :                   && actual_val == desired_val - 1)
    2755              :                 {
    2756            0 :                   code = LT;
    2757            0 :                   op_b = GEN_INT (desired_val);
    2758              :                 }
    2759              :               break;
    2760         1692 :             case GT:
    2761         1692 :               if (desired_val != HOST_WIDE_INT_MIN
    2762         1692 :                   && actual_val == desired_val - 1)
    2763              :                 {
    2764          249 :                   code = GE;
    2765          249 :                   op_b = GEN_INT (desired_val);
    2766              :                 }
    2767              :               break;
    2768           40 :             case GE:
    2769           40 :               if (desired_val != HOST_WIDE_INT_MAX
    2770           25 :                   && actual_val == desired_val + 1)
    2771              :                 {
    2772            3 :                   code = GT;
    2773            3 :                   op_b = GEN_INT (desired_val);
    2774              :                 }
    2775              :               break;
    2776              :             default:
    2777              :               break;
    2778              :             }
    2779              :         }
    2780              : 
    2781              :       /* If we made any changes, generate a new conditional that is
    2782              :          equivalent to what we started with, but has the right
    2783              :          constants in it.  */
    2784        46547 :       if (code != GET_CODE (if_info->cond)
    2785        45611 :           || op_a != XEXP (if_info->cond, 0)
    2786        45610 :           || op_b != XEXP (if_info->cond, 1))
    2787              :         {
    2788         2010 :           cond = gen_rtx_fmt_ee (code, GET_MODE (cond), op_a, op_b);
    2789         2010 :           *earliest = if_info->cond_earliest;
    2790         2010 :           return cond;
    2791              :         }
    2792              :     }
    2793              : 
    2794       152281 :   cond = canonicalize_condition (if_info->jump, cond, reverse,
    2795              :                                  earliest, target, have_cbranchcc4, true);
    2796       152281 :   if (! cond || ! reg_mentioned_p (target, cond))
    2797       152281 :     return NULL;
    2798              : 
    2799              :   /* We almost certainly searched back to a different place.
    2800              :      Need to re-verify correct lifetimes.  */
    2801              : 
    2802              :   /* X may not be mentioned in the range (cond_earliest, jump].  */
    2803            0 :   for (insn = if_info->jump; insn != *earliest; insn = PREV_INSN (insn))
    2804            0 :     if (INSN_P (insn) && reg_overlap_mentioned_p (if_info->x, PATTERN (insn)))
    2805              :       return NULL;
    2806              : 
    2807              :   /* A and B may not be modified in the range [cond_earliest, jump).  */
    2808            0 :   for (insn = *earliest; insn != if_info->jump; insn = NEXT_INSN (insn))
    2809            0 :     if (INSN_P (insn)
    2810            0 :         && (modified_in_p (if_info->a, insn)
    2811            0 :             || modified_in_p (if_info->b, insn)))
    2812            0 :       return NULL;
    2813              : 
    2814              :   return cond;
    2815              : }
    2816              : 
    2817              : /* Convert "if (a < b) x = a; else x = b;" to "x = min(a, b);", etc.  */
    2818              : 
    2819              : static bool
    2820       209887 : noce_try_minmax (struct noce_if_info *if_info)
    2821              : {
    2822       209887 :   rtx cond, target;
    2823       209887 :   rtx_insn *earliest, *seq;
    2824       209887 :   enum rtx_code code, op;
    2825       209887 :   bool unsignedp;
    2826              : 
    2827       465666 :   if (!noce_simple_bbs (if_info))
    2828              :     return false;
    2829              : 
    2830              :   /* ??? Reject modes with NaNs or signed zeros since we don't know how
    2831              :      they will be resolved with an SMIN/SMAX.  It wouldn't be too hard
    2832              :      to get the target to tell us...  */
    2833       192293 :   if (HONOR_SIGNED_ZEROS (if_info->x)
    2834       192293 :       || HONOR_NANS (if_info->x))
    2835        31208 :     return false;
    2836              : 
    2837       161085 :   cond = noce_get_alt_condition (if_info, if_info->a, &earliest);
    2838       161085 :   if (!cond)
    2839              :     return false;
    2840              : 
    2841              :   /* Verify the condition is of the form we expect, and canonicalize
    2842              :      the comparison code.  */
    2843         9789 :   code = GET_CODE (cond);
    2844         9789 :   if (rtx_equal_p (XEXP (cond, 0), if_info->a))
    2845              :     {
    2846         2526 :       if (! rtx_equal_p (XEXP (cond, 1), if_info->b))
    2847              :         return false;
    2848              :     }
    2849         7263 :   else if (rtx_equal_p (XEXP (cond, 1), if_info->a))
    2850              :     {
    2851         4278 :       if (! rtx_equal_p (XEXP (cond, 0), if_info->b))
    2852              :         return false;
    2853           39 :       code = swap_condition (code);
    2854              :     }
    2855              :   else
    2856              :     return false;
    2857              : 
    2858              :   /* Determine what sort of operation this is.  Note that the code is for
    2859              :      a taken branch, so the code->operation mapping appears backwards.  */
    2860           52 :   switch (code)
    2861              :     {
    2862              :     case LT:
    2863              :     case LE:
    2864              :     case UNLT:
    2865              :     case UNLE:
    2866              :       op = SMAX;
    2867              :       unsignedp = false;
    2868              :       break;
    2869            8 :     case GT:
    2870            8 :     case GE:
    2871            8 :     case UNGT:
    2872            8 :     case UNGE:
    2873            8 :       op = SMIN;
    2874            8 :       unsignedp = false;
    2875            8 :       break;
    2876            3 :     case LTU:
    2877            3 :     case LEU:
    2878            3 :       op = UMAX;
    2879            3 :       unsignedp = true;
    2880            3 :       break;
    2881           20 :     case GTU:
    2882           20 :     case GEU:
    2883           20 :       op = UMIN;
    2884           20 :       unsignedp = true;
    2885           20 :       break;
    2886              :     default:
    2887              :       return false;
    2888              :     }
    2889              : 
    2890           52 :   start_sequence ();
    2891              : 
    2892           52 :   target = expand_simple_binop (GET_MODE (if_info->x), op,
    2893              :                                 if_info->a, if_info->b,
    2894              :                                 if_info->x, unsignedp, OPTAB_WIDEN);
    2895           52 :   if (! target)
    2896              :     {
    2897            0 :       end_sequence ();
    2898            0 :       return false;
    2899              :     }
    2900           52 :   if (target != if_info->x)
    2901            0 :     noce_emit_move_insn (if_info->x, target);
    2902              : 
    2903           52 :   seq = end_ifcvt_sequence (if_info);
    2904           52 :   if (!seq)
    2905              :     return false;
    2906              : 
    2907           52 :   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
    2908           52 :   if_info->cond = cond;
    2909           52 :   if_info->cond_earliest = earliest;
    2910           52 :   if_info->rev_cond = NULL_RTX;
    2911           52 :   if_info->transform_name = "noce_try_minmax";
    2912              : 
    2913           52 :   return true;
    2914              : }
    2915              : 
    2916              : /* Convert "if (a < 0) x = -a; else x = a;" to "x = abs(a);",
    2917              :    "if (a < 0) x = ~a; else x = a;" to "x = one_cmpl_abs(a);",
    2918              :    etc.  */
    2919              : 
    2920              : static bool
    2921       209835 : noce_try_abs (struct noce_if_info *if_info)
    2922              : {
    2923       209835 :   rtx cond, target, a, b, c;
    2924       209835 :   rtx_insn *earliest, *seq;
    2925       209835 :   bool negate;
    2926       209835 :   bool one_cmpl = false;
    2927              : 
    2928       465580 :   if (!noce_simple_bbs (if_info))
    2929              :     return false;
    2930              : 
    2931              :   /* Reject modes with signed zeros.  */
    2932       192241 :   if (HONOR_SIGNED_ZEROS (if_info->x))
    2933              :     return false;
    2934              : 
    2935              :   /* Recognize A and B as constituting an ABS or NABS.  The canonical
    2936              :      form is a branch around the negation, taken when the object is the
    2937              :      first operand of a comparison against 0 that evaluates to true.  */
    2938       161041 :   a = if_info->a;
    2939       161041 :   b = if_info->b;
    2940       161041 :   if (GET_CODE (a) == NEG && rtx_equal_p (XEXP (a, 0), b))
    2941              :     negate = false;
    2942       160061 :   else if (GET_CODE (b) == NEG && rtx_equal_p (XEXP (b, 0), a))
    2943              :     {
    2944              :       std::swap (a, b);
    2945              :       negate = true;
    2946              :     }
    2947       160031 :   else if (GET_CODE (a) == NOT && rtx_equal_p (XEXP (a, 0), b))
    2948              :     {
    2949              :       negate = false;
    2950              :       one_cmpl = true;
    2951              :     }
    2952       160031 :   else if (GET_CODE (b) == NOT && rtx_equal_p (XEXP (b, 0), a))
    2953              :     {
    2954              :       std::swap (a, b);
    2955              :       negate = true;
    2956              :       one_cmpl = true;
    2957              :     }
    2958              :   else
    2959       160031 :     return false;
    2960              : 
    2961         1010 :   cond = noce_get_alt_condition (if_info, b, &earliest);
    2962         1010 :   if (!cond)
    2963              :     return false;
    2964              : 
    2965              :   /* Verify the condition is of the form we expect.  */
    2966           25 :   if (rtx_equal_p (XEXP (cond, 0), b))
    2967           25 :     c = XEXP (cond, 1);
    2968            0 :   else if (rtx_equal_p (XEXP (cond, 1), b))
    2969              :     {
    2970            0 :       c = XEXP (cond, 0);
    2971            0 :       negate = !negate;
    2972              :     }
    2973              :   else
    2974              :     return false;
    2975              : 
    2976              :   /* Verify that C is zero.  Search one step backward for a
    2977              :      REG_EQUAL note or a simple source if necessary.  */
    2978           25 :   if (REG_P (c))
    2979              :     {
    2980            0 :       rtx set;
    2981            0 :       rtx_insn *insn = prev_nonnote_nondebug_insn (earliest);
    2982            0 :       if (insn
    2983            0 :           && BLOCK_FOR_INSN (insn) == BLOCK_FOR_INSN (earliest)
    2984            0 :           && (set = single_set (insn))
    2985            0 :           && rtx_equal_p (SET_DEST (set), c))
    2986              :         {
    2987            0 :           rtx note = find_reg_equal_equiv_note (insn);
    2988            0 :           if (note)
    2989            0 :             c = XEXP (note, 0);
    2990              :           else
    2991            0 :             c = SET_SRC (set);
    2992              :         }
    2993              :       else
    2994            0 :         return false;
    2995              :     }
    2996           25 :   if (MEM_P (c)
    2997            0 :       && GET_CODE (XEXP (c, 0)) == SYMBOL_REF
    2998           25 :       && CONSTANT_POOL_ADDRESS_P (XEXP (c, 0)))
    2999            0 :     c = get_pool_constant (XEXP (c, 0));
    3000              : 
    3001              :   /* Work around funny ideas get_condition has wrt canonicalization.
    3002              :      Note that these rtx constants are known to be CONST_INT, and
    3003              :      therefore imply integer comparisons.
    3004              :      The one_cmpl case is more complicated, as we want to handle
    3005              :      only x < 0 ? ~x : x or x >= 0 ? x : ~x to one_cmpl_abs (x)
    3006              :      and x < 0 ? x : ~x or x >= 0 ? ~x : x to ~one_cmpl_abs (x),
    3007              :      but not other cases (x > -1 is equivalent of x >= 0).  */
    3008           25 :   if (c == constm1_rtx && GET_CODE (cond) == GT)
    3009              :     ;
    3010            1 :   else if (c == const1_rtx && GET_CODE (cond) == LT)
    3011              :     {
    3012            0 :       if (one_cmpl)
    3013              :         return false;
    3014              :     }
    3015            1 :   else if (c == CONST0_RTX (GET_MODE (b)))
    3016              :     {
    3017            0 :       if (one_cmpl
    3018            0 :           && GET_CODE (cond) != GE
    3019            0 :           && GET_CODE (cond) != LT)
    3020              :         return false;
    3021              :     }
    3022              :   else
    3023              :     return false;
    3024              : 
    3025              :   /* Determine what sort of operation this is.  */
    3026           24 :   switch (GET_CODE (cond))
    3027              :     {
    3028            0 :     case LT:
    3029            0 :     case LE:
    3030            0 :     case UNLT:
    3031            0 :     case UNLE:
    3032            0 :       negate = !negate;
    3033            0 :       break;
    3034              :     case GT:
    3035              :     case GE:
    3036              :     case UNGT:
    3037              :     case UNGE:
    3038              :       break;
    3039              :     default:
    3040              :       return false;
    3041              :     }
    3042              : 
    3043           24 :   start_sequence ();
    3044           24 :   if (one_cmpl)
    3045            0 :     target = expand_one_cmpl_abs_nojump (GET_MODE (if_info->x), b,
    3046              :                                          if_info->x);
    3047              :   else
    3048           24 :     target = expand_abs_nojump (GET_MODE (if_info->x), b, if_info->x, 1);
    3049              : 
    3050              :   /* ??? It's a quandary whether cmove would be better here, especially
    3051              :      for integers.  Perhaps combine will clean things up.  */
    3052           24 :   if (target && negate)
    3053              :     {
    3054            0 :       if (one_cmpl)
    3055            0 :         target = expand_simple_unop (GET_MODE (target), NOT, target,
    3056              :                                      if_info->x, 0);
    3057              :       else
    3058            0 :         target = expand_simple_unop (GET_MODE (target), NEG, target,
    3059              :                                      if_info->x, 0);
    3060              :     }
    3061              : 
    3062           24 :   if (! target)
    3063              :     {
    3064            0 :       end_sequence ();
    3065            0 :       return false;
    3066              :     }
    3067              : 
    3068           24 :   if (target != if_info->x)
    3069            0 :     noce_emit_move_insn (if_info->x, target);
    3070              : 
    3071           24 :   seq = end_ifcvt_sequence (if_info);
    3072           24 :   if (!seq)
    3073              :     return false;
    3074              : 
    3075           24 :   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
    3076           24 :   if_info->cond = cond;
    3077           24 :   if_info->cond_earliest = earliest;
    3078           24 :   if_info->rev_cond = NULL_RTX;
    3079           24 :   if_info->transform_name = "noce_try_abs";
    3080              : 
    3081           24 :   return true;
    3082              : }
    3083              : 
    3084              : /* Convert "if (m < 0) x = b; else x = 0;" to "x = (m >> C) & b;".  */
    3085              : 
    3086              : static bool
    3087       112891 : noce_try_sign_mask (struct noce_if_info *if_info)
    3088              : {
    3089       112891 :   rtx cond, t, m, c;
    3090       112891 :   rtx_insn *seq;
    3091       112891 :   machine_mode mode;
    3092       112891 :   enum rtx_code code;
    3093       112891 :   bool t_unconditional;
    3094              : 
    3095       240733 :   if (!noce_simple_bbs (if_info))
    3096              :     return false;
    3097              : 
    3098       101671 :   cond = if_info->cond;
    3099       101671 :   code = GET_CODE (cond);
    3100       101671 :   m = XEXP (cond, 0);
    3101       101671 :   c = XEXP (cond, 1);
    3102              : 
    3103       101671 :   t = NULL_RTX;
    3104       101671 :   if (if_info->a == const0_rtx)
    3105              :     {
    3106         2312 :       if ((code == LT && c == const0_rtx)
    3107         2283 :           || (code == LE && c == constm1_rtx))
    3108           29 :         t = if_info->b;
    3109              :     }
    3110        99359 :   else if (if_info->b == const0_rtx)
    3111              :     {
    3112        10959 :       if ((code == GE && c == const0_rtx)
    3113        10959 :           || (code == GT && c == constm1_rtx))
    3114              :         t = if_info->a;
    3115              :     }
    3116              : 
    3117           95 :   if (! t || side_effects_p (t))
    3118       101576 :     return false;
    3119              : 
    3120              :   /* We currently don't handle different modes.  */
    3121           95 :   mode = GET_MODE (t);
    3122           95 :   if (GET_MODE (m) != mode)
    3123              :     return false;
    3124              : 
    3125              :   /* This is only profitable if T is unconditionally executed/evaluated in the
    3126              :      original insn sequence or T is cheap and can't trap or fault.  The former
    3127              :      happens if B is the non-zero (T) value and if INSN_B was taken from
    3128              :      TEST_BB, or there was no INSN_B which can happen for e.g. conditional
    3129              :      stores to memory.  For the cost computation use the block TEST_BB where
    3130              :      the evaluation will end up after the transformation.  */
    3131           43 :   t_unconditional
    3132           86 :     = (t == if_info->b
    3133           43 :        && (if_info->insn_b == NULL_RTX
    3134            0 :            || BLOCK_FOR_INSN (if_info->insn_b) == if_info->test_bb));
    3135           86 :   if (!(t_unconditional
    3136           43 :         || ((set_src_cost (t, mode, if_info->speed_p)
    3137              :              < COSTS_N_INSNS (2))
    3138           37 :             && !may_trap_or_fault_p (t))))
    3139           43 :     return false;
    3140              : 
    3141            0 :   if (!noce_can_force_operand (t))
    3142              :     return false;
    3143              : 
    3144            0 :   start_sequence ();
    3145              :   /* Use emit_store_flag to generate "m < 0 ? -1 : 0" instead of expanding
    3146              :      "(signed) m >> 31" directly.  This benefits targets with specialized
    3147              :      insns to obtain the signmask, but still uses ashr_optab otherwise.  */
    3148            0 :   m = emit_store_flag (gen_reg_rtx (mode), LT, m, const0_rtx, mode, 0, -1);
    3149            0 :   t = m ? expand_binop (mode, and_optab, m, t, NULL_RTX, 0, OPTAB_DIRECT)
    3150              :         : NULL_RTX;
    3151              : 
    3152            0 :   if (!t)
    3153              :     {
    3154            0 :       end_sequence ();
    3155            0 :       return false;
    3156              :     }
    3157              : 
    3158            0 :   noce_emit_move_insn (if_info->x, t);
    3159              : 
    3160            0 :   seq = end_ifcvt_sequence (if_info);
    3161            0 :   if (!seq)
    3162              :     return false;
    3163              : 
    3164            0 :   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
    3165            0 :   if_info->transform_name = "noce_try_sign_mask";
    3166              : 
    3167            0 :   return true;
    3168              : }
    3169              : 
    3170              : /*  Check if OP is supported by conditional zero based if conversion,
    3171              :     returning TRUE if satisfied otherwise FALSE.
    3172              : 
    3173              :     OP is the operation to check.  */
    3174              : 
    3175              : static bool
    3176       113338 : noce_cond_zero_binary_op_supported (rtx op)
    3177              : {
    3178       113338 :   enum rtx_code opcode = GET_CODE (op);
    3179              : 
    3180            0 :   if (opcode == PLUS || opcode == MINUS || opcode == IOR || opcode == XOR
    3181              :       || opcode == ASHIFT || opcode == ASHIFTRT || opcode == LSHIFTRT
    3182              :       || opcode == ROTATE || opcode == ROTATERT || opcode == AND)
    3183            0 :     return true;
    3184              : 
    3185              :   return false;
    3186              : }
    3187              : 
    3188              : /*  Helper function to return REG itself,
    3189              :     otherwise NULL_RTX for other RTX_CODE.  */
    3190              : 
    3191              : static rtx
    3192        26072 : get_base_reg (rtx exp)
    3193              : {
    3194            0 :   if (REG_P (exp))
    3195              :     return exp;
    3196         6918 :   else if (SUBREG_P (exp))
    3197            0 :     return SUBREG_REG (exp);
    3198              : 
    3199              :   return NULL_RTX;
    3200              : }
    3201              : 
    3202              : /*  Try to covert if-then-else with conditional zero,
    3203              :     returning TURE on success or FALSE on failure.
    3204              :     IF_INFO describes the if-conversion scenario under consideration.
    3205              : 
    3206              :     It verifies the branch structure on left and transforms it into branchless
    3207              :     sequence on the right, with a backend provided conditional zero or orig for
    3208              :     operand z. If true, tmp is z, 0 otherwise (y op 0 is same as y for most op).
    3209              : 
    3210              :       if (cond)         |  tmp = cond ? z : 0
    3211              :         x = y op z      |    x = y op tmp
    3212              :       else              |
    3213              :         x = y           |
    3214              : 
    3215              :     AND is special as it needs to be handled differently.
    3216              : 
    3217              :       tmp = !cond ? y : 0
    3218              :         x = (y & z) | tmp
    3219              :     Also for AND try:
    3220              :       tmp = cond ? z : -1
    3221              :         x = y op tmp
    3222              :     To see if it is cheaper to produce `!cond ? y : 0`
    3223              :     or `cond ? z : -1`.
    3224              :   */
    3225              : 
    3226              : static int
    3227       159543 : noce_try_cond_arith (struct noce_if_info *if_info)
    3228              : {
    3229       159543 :   rtx target, a, b, a_op0, a_op1;
    3230       159543 :   rtx cond = if_info->cond;
    3231       159543 :   rtx_code code = GET_CODE (cond);
    3232       159543 :   rtx_insn *seq;
    3233       159543 :   rtx_code op;
    3234       159543 :   machine_mode mode = GET_MODE (if_info->x);
    3235              : 
    3236              :   /* Scalar integral modes are only supported here.
    3237              :      Could support scalar floating point but that
    3238              :      would be only with -ffast-math and might
    3239              :      be worse than a branch.  */
    3240       159543 :   if (!SCALAR_INT_MODE_P (mode))
    3241              :     return false;
    3242              : 
    3243       301997 :   if (!noce_simple_bbs (if_info))
    3244              :     return false;
    3245              : 
    3246       112221 :   a = copy_rtx (if_info->a);
    3247       112221 :   b = copy_rtx (if_info->b);
    3248              : 
    3249              :   /* Canonicalize x = y : (y op z) to x = (y op z) : y.  */
    3250       112221 :   if (REG_P (a) && noce_cond_zero_binary_op_supported (b))
    3251              :     {
    3252          272 :       if (if_info->rev_cond)
    3253              :         {
    3254          272 :           cond = if_info->rev_cond;
    3255          272 :           code = GET_CODE (cond);
    3256              :         }
    3257              :       else
    3258            0 :         code = reversed_comparison_code (cond, if_info->jump);
    3259              :       std::swap (a, b);
    3260              :     }
    3261              : 
    3262              :   /* Check if x = (y op z) : y is supported by czero based ifcvt.  */
    3263       111949 :   else if (!(noce_cond_zero_binary_op_supported (a) && REG_P (b)))
    3264        95862 :     goto fail;
    3265              : 
    3266        16359 :   if (code == UNKNOWN)
    3267            0 :     goto fail;
    3268              : 
    3269        16359 :   op = GET_CODE (a);
    3270              : 
    3271              :   /* Canonicalize x = (z op y) : y to x = (y op z) : y */
    3272        16359 :   a_op1 = get_base_reg (XEXP (a, 1));
    3273         9712 :   if (a_op1 && rtx_equal_p (a_op1, b) && COMMUTATIVE_ARITH_P (a))
    3274              :     {
    3275           14 :       std::swap (XEXP (a, 0), XEXP (a, 1));
    3276           14 :       a_op1 = get_base_reg (XEXP (a, 1));
    3277              :     }
    3278              : 
    3279        16345 :   if (a_op1 == NULL_RTX)
    3280         6660 :     goto fail;
    3281              : 
    3282              :   /* Ensure the cond is of form: x = (y op z) : y */
    3283         9699 :   a_op0 = get_base_reg (XEXP (a, 0));
    3284         9690 :   if (!(a_op0 && rtx_equal_p (a_op0, b)))
    3285          707 :     goto fail;
    3286              : 
    3287         8992 :   start_sequence ();
    3288              : 
    3289         8992 :   target = gen_reg_rtx (GET_MODE (XEXP (a, op != AND)));
    3290              : 
    3291              :   /* AND requires !cond, instead we swap ops around.  */
    3292         8992 :   target = noce_emit_cmove (if_info, target, code,
    3293              :                             XEXP (cond, 0), XEXP (cond, 1),
    3294              :                             op != AND ? XEXP (a, 1) : const0_rtx,
    3295              :                             op != AND ? const0_rtx : XEXP (a, 0));
    3296         8992 :   if (!target)
    3297              :     {
    3298          386 :       end_sequence ();
    3299          386 :       rtx tmp = XEXP (a, op != AND);
    3300              :       /* If the cmove fails and this was a lowpart subreg,
    3301              :          then try the reg part and then putting back the lowpart
    3302              :          afterwards.  */
    3303          386 :       if (GET_CODE (tmp) != SUBREG  || !subreg_lowpart_p (tmp))
    3304          386 :         return false;
    3305            0 :       tmp = SUBREG_REG (tmp);
    3306              :       /* Only handle integer scalar modes for the inner mode of
    3307              :          the subreg.  */
    3308            0 :       if (!SCALAR_INT_MODE_P (GET_MODE (tmp)))
    3309              :         return false;
    3310              : 
    3311            0 :       start_sequence ();
    3312            0 :       target = gen_reg_rtx (GET_MODE (tmp));
    3313            0 :       target = noce_emit_cmove (if_info, target, code,
    3314              :                                 XEXP (cond, 0), XEXP (cond, 1),
    3315              :                                 op != AND ? tmp : const0_rtx,
    3316              :                                 op != AND ? const0_rtx : tmp);
    3317            0 :       if (!target)
    3318            0 :         goto end_seq_n_fail;
    3319            0 :       target = rtl_hooks.gen_lowpart_no_emit (GET_MODE (XEXP (a, op != AND)), target);
    3320            0 :       gcc_assert (target);
    3321              :     }
    3322              : 
    3323              :   /* For AND, try `cond ? z : -1` to see if that is cheaper or the same cost.
    3324              :      In some cases it will be cheaper to produce the -1 rather than the 0 case.  */
    3325         8606 :   if (op == AND)
    3326              :     {
    3327            6 :       rtx_insn *seq0 = end_sequence ();
    3328            6 :       unsigned cost0 = seq_cost (seq0, if_info->speed_p);
    3329            6 :       if (!target)
    3330              :         cost0 = -1u;
    3331              : 
    3332              :       /* Produce `cond ? z : -1`. */
    3333            6 :       rtx targetm1;
    3334            6 :       start_sequence ();
    3335            6 :       targetm1 = gen_reg_rtx (GET_MODE (XEXP (a, 1)));
    3336            6 :       targetm1 = noce_emit_cmove (if_info, targetm1, code,
    3337              :                                   XEXP (cond, 0), XEXP (cond, 1),
    3338              :                                   XEXP (a, 1), constm1_rtx);
    3339            6 :       rtx_insn *seqm1 = end_sequence ();
    3340            6 :       unsigned costm1 = seq_cost (seqm1, if_info->speed_p);
    3341            6 :       if (!targetm1)
    3342            0 :         costm1 = -1u;
    3343              :       /* If both fails, then there is no costing to be done. */
    3344            6 :       if (!targetm1 && !target)
    3345              :         return false;
    3346              : 
    3347              :       /* If -1 is cheaper or the same cost to producing 0, then use that.  */
    3348            6 :       if (costm1 <= cost0)
    3349              :         {
    3350            6 :           push_to_sequence (seqm1);
    3351            6 :           targetm1 = expand_simple_binop (mode, op, a_op0, targetm1,
    3352              :                                           if_info->x, 0, OPTAB_WIDEN);
    3353            6 :           if (targetm1)
    3354              :             {
    3355            6 :               target = targetm1;
    3356            6 :               goto success;
    3357              :             }
    3358            0 :           end_sequence ();
    3359              :         }
    3360            0 :       if (!target)
    3361              :         return false;
    3362              :       /* For 0 the produce sequence is:
    3363              :          tmp = !cond ? y : 0
    3364              :          x = (y & z) | tmp  */
    3365            0 :       push_to_sequence (seq0);
    3366            0 :       rtx a_bin = gen_reg_rtx (mode);
    3367            0 :       noce_emit_move_insn (a_bin, a);
    3368              : 
    3369            0 :       target = expand_simple_binop (mode, IOR, a_bin, target, if_info->x, 0,
    3370              :                                     OPTAB_WIDEN);
    3371            0 :       if (!target)
    3372            0 :         goto end_seq_n_fail;
    3373            0 :       goto success;
    3374              :     }
    3375         8600 :   if (!target)
    3376              :     goto end_seq_n_fail;
    3377              : 
    3378         8600 :   target = expand_simple_binop (mode, op, a_op0, target, if_info->x, 0,
    3379              :                                 OPTAB_WIDEN);
    3380              : 
    3381         8600 :   if (!target)
    3382            0 :     goto end_seq_n_fail;
    3383              : 
    3384         8600 : success:
    3385         8606 :   if (target != if_info->x)
    3386            0 :     noce_emit_move_insn (if_info->x, target);
    3387              : 
    3388         8606 :   seq = end_ifcvt_sequence (if_info);
    3389         8606 :   if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
    3390           45 :     goto fail;
    3391              : 
    3392         8561 :   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
    3393         8561 :   if_info->transform_name = "noce_try_cond_arith";
    3394         8561 :   return true;
    3395              : 
    3396            0 : end_seq_n_fail:
    3397            0 :   end_sequence ();
    3398              : 
    3399              : fail:
    3400              : 
    3401              :   return false;
    3402              : }
    3403              : 
    3404              : /* Optimize away "if (x & C) x |= C" and similar bit manipulation
    3405              :    transformations.  */
    3406              : 
    3407              : static bool
    3408       209887 : noce_try_bitop (struct noce_if_info *if_info)
    3409              : {
    3410       209887 :   rtx cond, x, a, result;
    3411       209887 :   rtx_insn *seq;
    3412       209887 :   scalar_int_mode mode;
    3413       209887 :   enum rtx_code code;
    3414       209887 :   int bitnum;
    3415              : 
    3416       209887 :   x = if_info->x;
    3417       209887 :   cond = if_info->cond;
    3418       209887 :   code = GET_CODE (cond);
    3419              : 
    3420              :   /* Check for an integer operation.  */
    3421       209887 :   if (!is_a <scalar_int_mode> (GET_MODE (x), &mode))
    3422              :     return false;
    3423              : 
    3424       428095 :   if (!noce_simple_bbs (if_info))
    3425              :     return false;
    3426              : 
    3427              :   /* Check for no else condition.  */
    3428       159705 :   if (! rtx_equal_p (x, if_info->b))
    3429              :     return false;
    3430              : 
    3431              :   /* Check for a suitable condition.  */
    3432        83871 :   if (code != NE && code != EQ)
    3433              :     return false;
    3434        59293 :   if (XEXP (cond, 1) != const0_rtx)
    3435              :     return false;
    3436        41259 :   cond = XEXP (cond, 0);
    3437              : 
    3438              :   /* ??? We could also handle AND here.  */
    3439        41259 :   if (GET_CODE (cond) == ZERO_EXTRACT)
    3440              :     {
    3441          281 :       if (XEXP (cond, 1) != const1_rtx
    3442          165 :           || !CONST_INT_P (XEXP (cond, 2))
    3443          446 :           || ! rtx_equal_p (x, XEXP (cond, 0)))
    3444          276 :         return false;
    3445            5 :       bitnum = INTVAL (XEXP (cond, 2));
    3446            5 :       if (BITS_BIG_ENDIAN)
    3447              :         bitnum = GET_MODE_BITSIZE (mode) - 1 - bitnum;
    3448            5 :       if (bitnum < 0 || bitnum >= HOST_BITS_PER_WIDE_INT)
    3449              :         return false;
    3450              :     }
    3451              :   else
    3452              :     return false;
    3453              : 
    3454            5 :   a = if_info->a;
    3455            5 :   if (GET_CODE (a) == IOR || GET_CODE (a) == XOR)
    3456              :     {
    3457              :       /* Check for "if (X & C) x = x op C".  */
    3458            0 :       if (! rtx_equal_p (x, XEXP (a, 0))
    3459            0 :           || !CONST_INT_P (XEXP (a, 1))
    3460            0 :           || (INTVAL (XEXP (a, 1)) & GET_MODE_MASK (mode))
    3461            0 :              != HOST_WIDE_INT_1U << bitnum)
    3462              :         return false;
    3463              : 
    3464              :       /* if ((x & C) == 0) x |= C; is transformed to x |= C.   */
    3465              :       /* if ((x & C) != 0) x |= C; is transformed to nothing.  */
    3466            0 :       if (GET_CODE (a) == IOR)
    3467            0 :         result = (code == NE) ? a : NULL_RTX;
    3468            0 :       else if (code == NE)
    3469              :         {
    3470              :           /* if ((x & C) == 0) x ^= C; is transformed to x |= C.   */
    3471            0 :           result = gen_int_mode (HOST_WIDE_INT_1 << bitnum, mode);
    3472            0 :           result = simplify_gen_binary (IOR, mode, x, result);
    3473              :         }
    3474              :       else
    3475              :         {
    3476              :           /* if ((x & C) != 0) x ^= C; is transformed to x &= ~C.  */
    3477            0 :           result = gen_int_mode (~(HOST_WIDE_INT_1 << bitnum), mode);
    3478            0 :           result = simplify_gen_binary (AND, mode, x, result);
    3479              :         }
    3480              :     }
    3481            5 :   else if (GET_CODE (a) == AND)
    3482              :     {
    3483              :       /* Check for "if (X & C) x &= ~C".  */
    3484            0 :       if (! rtx_equal_p (x, XEXP (a, 0))
    3485            0 :           || !CONST_INT_P (XEXP (a, 1))
    3486            0 :           || (INTVAL (XEXP (a, 1)) & GET_MODE_MASK (mode))
    3487            0 :              != (~(HOST_WIDE_INT_1 << bitnum) & GET_MODE_MASK (mode)))
    3488              :         return false;
    3489              : 
    3490              :       /* if ((x & C) == 0) x &= ~C; is transformed to nothing.  */
    3491              :       /* if ((x & C) != 0) x &= ~C; is transformed to x &= ~C.  */
    3492            0 :       result = (code == EQ) ? a : NULL_RTX;
    3493              :     }
    3494              :   else
    3495              :     return false;
    3496              : 
    3497            0 :   if (result)
    3498              :     {
    3499            0 :       start_sequence ();
    3500            0 :       noce_emit_move_insn (x, result);
    3501            0 :       seq = end_ifcvt_sequence (if_info);
    3502            0 :       if (!seq)
    3503              :         return false;
    3504              : 
    3505            0 :       emit_insn_before_setloc (seq, if_info->jump,
    3506            0 :                                INSN_LOCATION (if_info->insn_a));
    3507              :     }
    3508            0 :   if_info->transform_name = "noce_try_bitop";
    3509            0 :   return true;
    3510              : }
    3511              : 
    3512              : 
    3513              : /* Similar to get_condition, only the resulting condition must be
    3514              :    valid at JUMP, instead of at EARLIEST.
    3515              : 
    3516              :    If THEN_ELSE_REVERSED is true, the fallthrough does not go to the
    3517              :    THEN block of the caller, and we have to reverse the condition.  */
    3518              : 
    3519              : static rtx
    3520      4362974 : noce_get_condition (rtx_insn *jump, rtx_insn **earliest,
    3521              :                     bool then_else_reversed)
    3522              : {
    3523      4362974 :   rtx cond, set, tmp;
    3524      4362974 :   bool reverse;
    3525              : 
    3526      4362974 :   if (! any_condjump_p (jump))
    3527              :     return NULL_RTX;
    3528              : 
    3529      4362974 :   set = pc_set (jump);
    3530              : 
    3531              :   /* If this branches to JUMP_LABEL when the condition is false,
    3532              :      reverse the condition.  */
    3533      8725948 :   reverse = (GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
    3534      4362974 :              && label_ref_label (XEXP (SET_SRC (set), 2)) == JUMP_LABEL (jump));
    3535              : 
    3536              :   /* We may have to reverse because the caller's if block is not canonical,
    3537              :      i.e. the THEN block isn't the fallthrough block for the TEST block
    3538              :      (see find_if_header).  */
    3539      4362974 :   if (then_else_reversed)
    3540      1911587 :     reverse = !reverse;
    3541              : 
    3542              :   /* If the condition variable is a register and is MODE_INT, accept it.  */
    3543              : 
    3544      4362974 :   cond = XEXP (SET_SRC (set), 0);
    3545      4362974 :   tmp = XEXP (cond, 0);
    3546      4362031 :   if (REG_P (tmp) && GET_MODE_CLASS (GET_MODE (tmp)) == MODE_INT
    3547      4363014 :       && (GET_MODE (tmp) != BImode
    3548            0 :           || !targetm.small_register_classes_for_mode_p (BImode)))
    3549              :     {
    3550           40 :       *earliest = jump;
    3551              : 
    3552           40 :       if (reverse)
    3553           17 :         cond = gen_rtx_fmt_ee (reverse_condition (GET_CODE (cond)),
    3554              :                                GET_MODE (cond), tmp, XEXP (cond, 1));
    3555           40 :       return cond;
    3556              :     }
    3557              : 
    3558              :   /* Otherwise, fall back on canonicalize_condition to do the dirty
    3559              :      work of manipulating MODE_CC values and COMPARE rtx codes.  */
    3560      4362934 :   tmp = canonicalize_condition (jump, cond, reverse, earliest,
    3561              :                                 NULL_RTX, have_cbranchcc4, true);
    3562              : 
    3563              :   /* We don't handle side-effects in the condition, like handling
    3564              :      REG_INC notes and making sure no duplicate conditions are emitted.  */
    3565      4362934 :   if (tmp != NULL_RTX && side_effects_p (tmp))
    3566              :     return NULL_RTX;
    3567              : 
    3568              :   return tmp;
    3569              : }
    3570              : 
    3571              : /* Return true if OP is ok for if-then-else processing.  */
    3572              : 
    3573              : static bool
    3574      8901441 : noce_operand_ok (const_rtx op)
    3575              : {
    3576      8901441 :   if (side_effects_p (op))
    3577              :     return false;
    3578              : 
    3579              :   /* We special-case memories, so handle any of them with
    3580              :      no address side effects.  */
    3581      8880786 :   if (MEM_P (op))
    3582      1582937 :     return ! side_effects_p (XEXP (op, 0));
    3583              : 
    3584      7297849 :   return ! may_trap_p (op);
    3585              : }
    3586              : 
    3587              : /* Return true iff basic block TEST_BB is valid for noce if-conversion.
    3588              :    The condition used in this if-conversion is in COND.
    3589              :    In practice, check that TEST_BB ends with a single set
    3590              :    x := a and all previous computations
    3591              :    in TEST_BB don't produce any values that are live after TEST_BB.
    3592              :    In other words, all the insns in TEST_BB are there only
    3593              :    to compute a value for x.  Add the rtx cost of the insns
    3594              :    in TEST_BB to COST.  Record whether TEST_BB is a single simple
    3595              :    set instruction in SIMPLE_P.  */
    3596              : 
    3597              : static bool
    3598      2172772 : bb_valid_for_noce_process_p (basic_block test_bb, rtx cond,
    3599              :                               unsigned int *cost, bool *simple_p)
    3600              : {
    3601      2172772 :   if (!test_bb)
    3602              :     return false;
    3603              : 
    3604      2172772 :   rtx_insn *last_insn = last_active_insn (test_bb, false);
    3605      2172772 :   rtx last_set = NULL_RTX;
    3606              : 
    3607      2172772 :   rtx cc = cc_in_cond (cond);
    3608              : 
    3609      2172772 :   if (!insn_valid_noce_process_p (last_insn, cc))
    3610              :     return false;
    3611              : 
    3612              :   /* Punt on blocks ending with asm goto or jumps with other side-effects,
    3613              :      last_active_insn ignores JUMP_INSNs.  */
    3614      1537469 :   if (JUMP_P (BB_END (test_bb)) && !onlyjump_p (BB_END (test_bb)))
    3615              :     return false;
    3616              : 
    3617      1537467 :   last_set = single_set (last_insn);
    3618              : 
    3619      1537467 :   rtx x = SET_DEST (last_set);
    3620      1537467 :   rtx_insn *first_insn = first_active_insn (test_bb);
    3621      1537467 :   rtx first_set = single_set (first_insn);
    3622              : 
    3623      1537467 :   if (!first_set)
    3624              :     return false;
    3625              : 
    3626              :   /* We have a single simple set, that's okay.  */
    3627      1523375 :   bool speed_p = optimize_bb_for_speed_p (test_bb);
    3628              : 
    3629      1523375 :   if (first_insn == last_insn)
    3630              :     {
    3631       563067 :       *simple_p = noce_operand_ok (SET_DEST (first_set));
    3632       563067 :       *cost += pattern_cost (first_set, speed_p);
    3633       563067 :       return *simple_p;
    3634              :     }
    3635              : 
    3636       960308 :   rtx_insn *prev_last_insn = PREV_INSN (last_insn);
    3637       960308 :   gcc_assert (prev_last_insn);
    3638              : 
    3639              :   /* For now, disallow setting x multiple times in test_bb.  */
    3640       960308 :   if (REG_P (x) && reg_set_between_p (x, first_insn, prev_last_insn))
    3641              :     return false;
    3642              : 
    3643       813676 :   bitmap test_bb_temps = BITMAP_ALLOC (&reg_obstack);
    3644              : 
    3645              :   /* The regs that are live out of test_bb.  */
    3646       813676 :   bitmap test_bb_live_out = df_get_live_out (test_bb);
    3647              : 
    3648       813676 :   int potential_cost = pattern_cost (last_set, speed_p);
    3649       813676 :   rtx_insn *insn;
    3650      4204557 :   FOR_BB_INSNS (test_bb, insn)
    3651              :     {
    3652      4112784 :       if (insn != last_insn)
    3653              :         {
    3654      4021011 :           if (!active_insn_p (insn))
    3655      2583451 :             continue;
    3656              : 
    3657      1437560 :           if (!insn_valid_noce_process_p (insn, cc))
    3658       215599 :             goto free_bitmap_and_fail;
    3659              : 
    3660      1221961 :           rtx sset = single_set (insn);
    3661      1221961 :           gcc_assert (sset);
    3662      1221961 :           rtx dest = SET_DEST (sset);
    3663      1221961 :           if (SUBREG_P (dest))
    3664        18438 :             dest = SUBREG_REG (dest);
    3665              : 
    3666      1221961 :           if (contains_mem_rtx_p (SET_SRC (sset))
    3667       854865 :               || !REG_P (dest)
    3668      1948980 :               || reg_overlap_mentioned_p (dest, cond))
    3669       506304 :             goto free_bitmap_and_fail;
    3670              : 
    3671       715657 :           potential_cost += pattern_cost (sset, speed_p);
    3672       715657 :           bitmap_set_bit (test_bb_temps, REGNO (dest));
    3673              :         }
    3674              :     }
    3675              : 
    3676              :   /* If any of the intermediate results in test_bb are live after test_bb
    3677              :      then fail.  */
    3678        91773 :   if (bitmap_intersect_p (test_bb_live_out, test_bb_temps))
    3679        62740 :     goto free_bitmap_and_fail;
    3680              : 
    3681        29033 :   BITMAP_FREE (test_bb_temps);
    3682        29033 :   *cost += potential_cost;
    3683        29033 :   *simple_p = false;
    3684        29033 :   return true;
    3685              : 
    3686       784643 :  free_bitmap_and_fail:
    3687       784643 :   BITMAP_FREE (test_bb_temps);
    3688       784643 :   return false;
    3689              : }
    3690              : 
    3691              : /* Helper function to emit a cmov sequence encapsulated in
    3692              :    start_sequence () and end_sequence ().  If NEED_CMOV is true
    3693              :    we call noce_emit_cmove to create a cmove sequence.  Otherwise emit
    3694              :    a simple move.  If successful, store the first instruction of the
    3695              :    sequence in TEMP_DEST and the sequence costs in SEQ_COST.  */
    3696              : 
    3697              : static rtx_insn*
    3698       268156 : try_emit_cmove_seq (struct noce_if_info *if_info, rtx temp,
    3699              :                     rtx cond, rtx new_val, rtx old_val, bool need_cmov,
    3700              :                     unsigned *cost, rtx *temp_dest,
    3701              :                     rtx cc_cmp = NULL, rtx rev_cc_cmp = NULL)
    3702              : {
    3703       268156 :   rtx_insn *seq = NULL;
    3704       268156 :   *cost = 0;
    3705              : 
    3706       268156 :   rtx x = XEXP (cond, 0);
    3707       268156 :   rtx y = XEXP (cond, 1);
    3708       268156 :   rtx_code cond_code = GET_CODE (cond);
    3709              : 
    3710       268156 :   start_sequence ();
    3711              : 
    3712       268156 :   if (need_cmov)
    3713       217841 :     *temp_dest = noce_emit_cmove (if_info, temp, cond_code,
    3714              :                                   x, y, new_val, old_val, cc_cmp, rev_cc_cmp);
    3715              :   else
    3716              :     {
    3717        50315 :       *temp_dest = temp;
    3718        50315 :       if (if_info->then_else_reversed)
    3719         1838 :         noce_emit_move_insn (temp, old_val);
    3720              :       else
    3721        48477 :         noce_emit_move_insn (temp, new_val);
    3722              :     }
    3723              : 
    3724       268156 :   if (*temp_dest != NULL_RTX)
    3725              :     {
    3726       262092 :       seq = get_insns ();
    3727       262092 :       *cost = seq_cost (seq, if_info->speed_p);
    3728              :     }
    3729              : 
    3730       268156 :   end_sequence ();
    3731              : 
    3732       268156 :   return seq;
    3733              : }
    3734              : 
    3735              : /* We have something like:
    3736              : 
    3737              :      if (x > y)
    3738              :        { i = EXPR_A; j = EXPR_B; k = EXPR_C; }
    3739              : 
    3740              :    Make it:
    3741              : 
    3742              :      tmp_i = (x > y) ? EXPR_A : i;
    3743              :      tmp_j = (x > y) ? EXPR_B : j;
    3744              :      tmp_k = (x > y) ? EXPR_C : k;
    3745              :      i = tmp_i;
    3746              :      j = tmp_j;
    3747              :      k = tmp_k;
    3748              : 
    3749              :    Subsequent passes are expected to clean up the extra moves.
    3750              : 
    3751              :    Look for special cases such as writes to one register which are
    3752              :    read back in another SET, as might occur in a swap idiom or
    3753              :    similar.
    3754              : 
    3755              :    These look like:
    3756              : 
    3757              :    if (x > y)
    3758              :      i = a;
    3759              :      j = i;
    3760              : 
    3761              :    Which we want to rewrite to:
    3762              : 
    3763              :      tmp_i = (x > y) ? a : i;
    3764              :      tmp_j = (x > y) ? tmp_i : j;
    3765              :      i = tmp_i;
    3766              :      j = tmp_j;
    3767              : 
    3768              :    We can catch these when looking at (SET x y) by keeping a list of the
    3769              :    registers we would have targeted before if-conversion and looking back
    3770              :    through it for an overlap with Y.  If we find one, we rewire the
    3771              :    conditional set to use the temporary we introduced earlier.
    3772              : 
    3773              :    IF_INFO contains the useful information about the block structure and
    3774              :    jump instructions.  */
    3775              : 
    3776              : static bool
    3777        30476 : noce_convert_multiple_sets (struct noce_if_info *if_info)
    3778              : {
    3779        30476 :   basic_block test_bb = if_info->test_bb;
    3780        30476 :   basic_block then_bb = if_info->then_bb;
    3781        30476 :   basic_block join_bb = if_info->join_bb;
    3782        30476 :   rtx_insn *jump = if_info->jump;
    3783        30476 :   rtx_insn *cond_earliest;
    3784        30476 :   rtx_insn *insn;
    3785              : 
    3786        30476 :   start_sequence ();
    3787              : 
    3788              :   /* Decompose the condition attached to the jump.  */
    3789        30476 :   rtx cond = noce_get_condition (jump, &cond_earliest, false);
    3790        30476 :   rtx x = XEXP (cond, 0);
    3791        30476 :   rtx y = XEXP (cond, 1);
    3792              : 
    3793        30476 :   auto_delete_vec<noce_multiple_sets_info> insn_info;
    3794        30476 :   init_noce_multiple_sets_info (then_bb, insn_info);
    3795              : 
    3796        30476 :   int last_needs_comparison = -1;
    3797              : 
    3798        30476 :   bool use_cond_earliest = false;
    3799              : 
    3800        30476 :   bool ok = noce_convert_multiple_sets_1
    3801        30476 :     (if_info, insn_info, &last_needs_comparison, &use_cond_earliest);
    3802        30476 :   if (!ok)
    3803              :       return false;
    3804              : 
    3805              :   /* Always perform a second attempt that uses information gathered in the
    3806              :      first.  At least we can omit creating temporaries until we definitely
    3807              :      need them.  The sequence created in the second attempt is never worse
    3808              :      than the first.  */
    3809              : 
    3810        29366 :   end_sequence ();
    3811        29366 :   start_sequence ();
    3812        29366 :   ok = noce_convert_multiple_sets_1
    3813        29366 :     (if_info, insn_info, &last_needs_comparison, &use_cond_earliest);
    3814              : 
    3815              :   /* Actually we should not fail anymore if we reached here,
    3816              :      but better still check.  */
    3817        29366 :   if (!ok)
    3818              :     return false;
    3819              : 
    3820              :   /* We must have seen some sort of insn to insert, otherwise we were
    3821              :      given an empty BB to convert, and we can't handle that.  */
    3822        29366 :   gcc_assert (!insn_info.is_empty ());
    3823              : 
    3824              :   /* Now fixup the assignments.
    3825              :      PR116405: Iterate in reverse order and keep track of the targets so that
    3826              :      a move does not overwrite a subsequent value when multiple instructions
    3827              :      have the same target.  */
    3828        29366 :   unsigned i;
    3829        29366 :   noce_multiple_sets_info *info;
    3830        29366 :   bitmap set_targets = BITMAP_ALLOC (&reg_obstack);
    3831       108716 :   FOR_EACH_VEC_ELT_REVERSE (insn_info, i, info)
    3832              :     {
    3833        79350 :       gcc_checking_assert (REG_P (info->target));
    3834              : 
    3835        79350 :       if (info->target != info->temporary
    3836        79350 :           && !bitmap_bit_p (set_targets, REGNO (info->target)))
    3837         2748 :         noce_emit_move_insn (info->target, info->temporary);
    3838              : 
    3839        79350 :       bitmap_set_bit (set_targets, REGNO (info->target));
    3840              :     }
    3841        29366 :   BITMAP_FREE (set_targets);
    3842              : 
    3843              :   /* Actually emit the sequence if it isn't too expensive.  */
    3844        29366 :   rtx_insn *seq = get_insns ();
    3845              : 
    3846              :   /* If the created sequence does not use cond_earliest (but the jump
    3847              :      does) add its cost to the original_cost before comparing costs.  */
    3848        29366 :   unsigned int original_cost = if_info->original_cost;
    3849        29366 :   if (if_info->jump != if_info->cond_earliest && !use_cond_earliest)
    3850        18273 :     if_info->original_cost += insn_cost (if_info->cond_earliest,
    3851        18273 :                                          if_info->speed_p);
    3852              : 
    3853        29366 :   if (!targetm.noce_conversion_profitable_p (seq, if_info))
    3854              :     {
    3855         3829 :       end_sequence ();
    3856         3829 :       return false;
    3857              :     }
    3858              : 
    3859              :   /* Restore the original cost in case we do not succeed below.  */
    3860        25537 :   if_info->original_cost = original_cost;
    3861              : 
    3862       149497 :   for (insn = seq; insn; insn = NEXT_INSN (insn))
    3863       123960 :     set_used_flags (insn);
    3864              : 
    3865              :   /* Mark all our temporaries and targets as used.  */
    3866        89935 :   for (unsigned i = 0; i < insn_info.length (); i++)
    3867              :     {
    3868        64398 :       set_used_flags (insn_info[i]->temporary);
    3869        64398 :       set_used_flags (insn_info[i]->target);
    3870              :     }
    3871              : 
    3872        25537 :   set_used_flags (cond);
    3873        25537 :   set_used_flags (x);
    3874        25537 :   set_used_flags (y);
    3875              : 
    3876        25537 :   unshare_all_rtl_in_chain (seq);
    3877        25537 :   end_sequence ();
    3878              : 
    3879        25537 :   if (!seq)
    3880              :     return false;
    3881              : 
    3882       149318 :   for (insn = seq; insn; insn = NEXT_INSN (insn))
    3883       123826 :     if (JUMP_P (insn) || CALL_P (insn)
    3884       123826 :         || recog_memoized (insn) == -1)
    3885           45 :       return false;
    3886              : 
    3887        25492 :   emit_insn_before_setloc (seq, if_info->jump,
    3888        25492 :                            INSN_LOCATION (insn_info.last ()->unmodified_insn));
    3889              : 
    3890              :   /* Clean up THEN_BB and the edges in and out of it.  */
    3891        25492 :   remove_edge (find_edge (test_bb, join_bb));
    3892        25492 :   remove_edge (find_edge (then_bb, join_bb));
    3893        25492 :   redirect_edge_and_branch_force (single_succ_edge (test_bb), join_bb);
    3894        25492 :   delete_basic_block (then_bb);
    3895        25492 :   num_true_changes++;
    3896              : 
    3897              :   /* Maybe merge blocks now the jump is simple enough.  */
    3898        25492 :   if (can_merge_blocks_p (test_bb, join_bb))
    3899              :     {
    3900        16965 :       merge_blocks (test_bb, join_bb);
    3901        16965 :       num_true_changes++;
    3902              :     }
    3903              : 
    3904        25492 :   num_updated_if_blocks++;
    3905        25492 :   if_info->transform_name = "noce_convert_multiple_sets";
    3906        25492 :   return true;
    3907        30476 : }
    3908              : 
    3909              : /* This goes through all relevant insns of IF_INFO->then_bb and tries to create
    3910              :    conditional moves.  Information for the insns is kept in INSN_INFO.  */
    3911              : 
    3912              : static bool
    3913        59842 : noce_convert_multiple_sets_1 (struct noce_if_info *if_info,
    3914              :                               auto_delete_vec<noce_multiple_sets_info> &insn_info,
    3915              :                               int *last_needs_comparison,
    3916              :                               bool *use_cond_earliest)
    3917              : {
    3918        59842 :   basic_block then_bb = if_info->then_bb;
    3919        59842 :   rtx_insn *jump = if_info->jump;
    3920        59842 :   rtx_insn *cond_earliest;
    3921              : 
    3922              :   /* Decompose the condition attached to the jump.  */
    3923        59842 :   rtx cond = noce_get_condition (jump, &cond_earliest, false);
    3924              : 
    3925        59842 :   rtx cc_cmp = cond_exec_get_condition (jump);
    3926        59842 :   if (cc_cmp)
    3927        59842 :     cc_cmp = copy_rtx (cc_cmp);
    3928        59842 :   rtx rev_cc_cmp = cond_exec_get_condition (jump, /* get_reversed */ true);
    3929        59842 :   if (rev_cc_cmp)
    3930        59842 :     rev_cc_cmp = copy_rtx (rev_cc_cmp);
    3931              : 
    3932        59842 :   rtx_insn *insn;
    3933        59842 :   int count = 0;
    3934        59842 :   bool second_try = *last_needs_comparison != -1;
    3935        59842 :   *use_cond_earliest = false;
    3936              : 
    3937       360686 :   FOR_BB_INSNS (then_bb, insn)
    3938              :     {
    3939              :       /* Skip over non-insns.  */
    3940       301954 :       if (!active_insn_p (insn))
    3941       140553 :         continue;
    3942              : 
    3943       161401 :       noce_multiple_sets_info *info = insn_info[count];
    3944              : 
    3945       161401 :       rtx set = single_set (insn);
    3946       161401 :       gcc_checking_assert (set);
    3947              : 
    3948       161401 :       rtx target = SET_DEST (set);
    3949       161401 :       rtx temp;
    3950              : 
    3951       161401 :       rtx new_val = SET_SRC (set);
    3952              : 
    3953       161401 :       int i, ii;
    3954       198923 :       FOR_EACH_VEC_ELT (info->rewired_src, i, ii)
    3955        37522 :         new_val = simplify_replace_rtx (new_val, insn_info[ii]->target,
    3956        37522 :                                         insn_info[ii]->temporary);
    3957              : 
    3958       161401 :       rtx old_val = target;
    3959              : 
    3960              :       /* As we are transforming
    3961              :          if (x > y)
    3962              :            {
    3963              :              a = b;
    3964              :              c = d;
    3965              :            }
    3966              :          into
    3967              :            a = (x > y) ...
    3968              :            c = (x > y) ...
    3969              : 
    3970              :          we potentially check x > y before every set.
    3971              :          Even though the check might be removed by subsequent passes, this means
    3972              :          that we cannot transform
    3973              :            if (x > y)
    3974              :              {
    3975              :                x = y;
    3976              :                ...
    3977              :              }
    3978              :          into
    3979              :            x = (x > y) ...
    3980              :            ...
    3981              :          since this would invalidate x and the following to-be-removed checks.
    3982              :          Therefore we introduce a temporary every time we are about to
    3983              :          overwrite a variable used in the check.  Costing of a sequence with
    3984              :          these is going to be inaccurate so only use temporaries when
    3985              :          needed.
    3986              : 
    3987              :          If performing a second try, we know how many insns require a
    3988              :          temporary.  For the last of these, we can omit creating one.  */
    3989       161401 :       if (reg_overlap_mentioned_p (target, cond)
    3990       161401 :           && (!second_try || count < *last_needs_comparison))
    3991        20600 :         temp = gen_reg_rtx (GET_MODE (target));
    3992              :       else
    3993              :         temp = target;
    3994              : 
    3995              :       /* We have identified swap-style idioms before.  A normal
    3996              :          set will need to be a cmov while the first instruction of a swap-style
    3997              :          idiom can be a regular move.  This helps with costing.  */
    3998       161401 :       bool need_cmov = info->need_cmov;
    3999              : 
    4000              :       /* If we had a non-canonical conditional jump (i.e. one where
    4001              :          the fallthrough is to the "else" case) we need to reverse
    4002              :          the conditional select.  */
    4003       161401 :       if (if_info->then_else_reversed)
    4004        50668 :         std::swap (old_val, new_val);
    4005              : 
    4006              :       /* Try emitting a conditional move passing the backend the
    4007              :          canonicalized comparison.  The backend is then able to
    4008              :          recognize expressions like
    4009              : 
    4010              :            if (x > y)
    4011              :              y = x;
    4012              : 
    4013              :          as min/max and emit an insn, accordingly.  */
    4014       161401 :       unsigned cost1 = 0, cost2 = 0;
    4015       161401 :       rtx_insn *seq, *seq1, *seq2 = NULL;
    4016       161401 :       rtx temp_dest = NULL_RTX, temp_dest1 = NULL_RTX, temp_dest2 = NULL_RTX;
    4017       161401 :       bool read_comparison = false;
    4018              : 
    4019       161401 :       seq1 = try_emit_cmove_seq (if_info, temp, cond,
    4020              :                                  new_val, old_val, need_cmov,
    4021              :                                  &cost1, &temp_dest1);
    4022              : 
    4023              :       /* Here, we try to pass the backend a non-canonicalized cc comparison
    4024              :          as well.  This allows the backend to emit a cmov directly without
    4025              :          creating an additional compare for each.  If successful, costing
    4026              :          is easier and this sequence is usually preferred.  */
    4027       161401 :       if (cc_cmp)
    4028              :         {
    4029       106755 :           seq2 = try_emit_cmove_seq (if_info, temp, cond,
    4030              :                                      new_val, old_val, need_cmov,
    4031              :                                      &cost2, &temp_dest2, cc_cmp, rev_cc_cmp);
    4032              : 
    4033              :           /* The if_then_else in SEQ2 may be affected when cc_cmp/rev_cc_cmp is
    4034              :              clobbered.  We can't safely use the sequence in this case.  */
    4035       187349 :           for (rtx_insn *iter = seq2; iter; iter = NEXT_INSN (iter))
    4036       119039 :             if (modified_in_p (cc_cmp, iter)
    4037       119039 :               || (rev_cc_cmp && modified_in_p (rev_cc_cmp, iter)))
    4038              :               {
    4039              :                 seq2 = NULL;
    4040              :                 break;
    4041              :               }
    4042              :         }
    4043              : 
    4044              :       /* The backend might have created a sequence that uses the
    4045              :          condition as a value.  Check this.  */
    4046              : 
    4047              :       /* We cannot handle anything more complex than a reg or constant.  */
    4048       161401 :       if (!REG_P (XEXP (cond, 0)) && !CONSTANT_P (XEXP (cond, 0)))
    4049       161401 :         read_comparison = true;
    4050              : 
    4051       161401 :       if (!REG_P (XEXP (cond, 1)) && !CONSTANT_P (XEXP (cond, 1)))
    4052       161401 :         read_comparison = true;
    4053              : 
    4054              :       rtx_insn *walk = seq2;
    4055              :       int if_then_else_count = 0;
    4056       238736 :       while (walk && !read_comparison)
    4057              :         {
    4058        77335 :           rtx exprs_to_check[2];
    4059        77335 :           unsigned int exprs_count = 0;
    4060              : 
    4061        77335 :           rtx set = single_set (walk);
    4062        77335 :           if (set && XEXP (set, 1)
    4063        77335 :               && GET_CODE (XEXP (set, 1)) == IF_THEN_ELSE)
    4064              :             {
    4065              :               /* We assume that this is the cmove created by the backend that
    4066              :                  naturally uses the condition.  */
    4067        49500 :               exprs_to_check[exprs_count++] = XEXP (XEXP (set, 1), 1);
    4068        49500 :               exprs_to_check[exprs_count++] = XEXP (XEXP (set, 1), 2);
    4069        49500 :               if_then_else_count++;
    4070              :             }
    4071        27835 :           else if (NONDEBUG_INSN_P (walk))
    4072        27835 :             exprs_to_check[exprs_count++] = PATTERN (walk);
    4073              : 
    4074              :           /* Bail if we get more than one if_then_else because the assumption
    4075              :              above may be incorrect.  */
    4076        77335 :           if (if_then_else_count > 1)
    4077              :             {
    4078            0 :               read_comparison = true;
    4079            0 :               break;
    4080              :             }
    4081              : 
    4082       204170 :           for (unsigned int i = 0; i < exprs_count; i++)
    4083              :             {
    4084       126835 :               subrtx_iterator::array_type array;
    4085       281109 :               FOR_EACH_SUBRTX (iter, array, exprs_to_check[i], NONCONST)
    4086       184316 :                 if (*iter != NULL_RTX
    4087       184316 :                     && (reg_overlap_mentioned_p (XEXP (cond, 0), *iter)
    4088       166862 :                     || reg_overlap_mentioned_p (XEXP (cond, 1), *iter)))
    4089              :                   {
    4090              :                     read_comparison = true;
    4091              :                     break;
    4092              :                   }
    4093       126835 :             }
    4094              : 
    4095        77335 :           walk = NEXT_INSN (walk);
    4096              :         }
    4097              : 
    4098              :       /* Check which version is less expensive.  */
    4099       161401 :       if (seq1 != NULL_RTX && (cost1 <= cost2 || seq2 == NULL_RTX))
    4100              :         {
    4101       109877 :           seq = seq1;
    4102       109877 :           temp_dest = temp_dest1;
    4103       109877 :           if (!second_try)
    4104        55798 :             *last_needs_comparison = count;
    4105              :         }
    4106         1111 :       else if (seq2 != NULL_RTX)
    4107              :         {
    4108        50573 :           seq = seq2;
    4109        50573 :           temp_dest = temp_dest2;
    4110        50573 :           if (!second_try && read_comparison)
    4111         8290 :             *last_needs_comparison = count;
    4112        50573 :           *use_cond_earliest = true;
    4113              :         }
    4114              :       else
    4115              :         {
    4116              :           /* Nothing worked, bail out.  */
    4117          951 :           end_sequence ();
    4118         1110 :           return false;
    4119              :         }
    4120              : 
    4121              :       /* Although we use temporaries if there is register overlap of COND and
    4122              :          TARGET, it is possible that SEQ modifies COND anyway.  For example,
    4123              :          COND may use the flags register and if INSN clobbers flags then
    4124              :          we may be unable to emit a valid sequence (e.g. in x86 that would
    4125              :          require saving and restoring the flags register).  */
    4126       106371 :       if (!second_try)
    4127       241653 :         for (rtx_insn *iter = seq; iter; iter = NEXT_INSN (iter))
    4128       160712 :           if (modified_in_p (cond, iter))
    4129              :             {
    4130          159 :               end_sequence ();
    4131          159 :               return false;
    4132              :             }
    4133              : 
    4134       160291 :       if (cc_cmp && seq == seq1)
    4135              :         {
    4136              :           /* Check if SEQ can clobber registers mentioned in cc_cmp/rev_cc_cmp.
    4137              :              If yes, we need to use only SEQ1 from that point on.
    4138              :              Only check when we use SEQ1 since we have already tested SEQ2.  */
    4139        76135 :           for (rtx_insn *iter = seq; iter; iter = NEXT_INSN (iter))
    4140        58571 :             if (modified_in_p (cc_cmp, iter)
    4141        58571 :               || (rev_cc_cmp && modified_in_p (rev_cc_cmp, iter)))
    4142              :               {
    4143              :                 cc_cmp = NULL_RTX;
    4144              :                 rev_cc_cmp = NULL_RTX;
    4145              :                 break;
    4146              :               }
    4147              :         }
    4148              : 
    4149              :       /* End the sub sequence and emit to the main sequence.  */
    4150       160291 :       emit_insn (seq);
    4151              : 
    4152              :       /* Bookkeeping.  */
    4153       160291 :       count++;
    4154              : 
    4155       160291 :       info->target = target;
    4156       160291 :       info->temporary = temp_dest;
    4157       160291 :       info->unmodified_insn = insn;
    4158              :     }
    4159              : 
    4160              :   /* Even if we did not actually need the comparison, we want to make sure
    4161              :      to try a second time in order to get rid of the temporaries.  */
    4162        58732 :   if (*last_needs_comparison == -1)
    4163          952 :     *last_needs_comparison = 0;
    4164              : 
    4165              :   return true;
    4166              : }
    4167              : 
    4168              : /* Find local swap-style idioms in BB and mark the first insn (1)
    4169              :    that is only a temporary as not needing a conditional move as
    4170              :    it is going to be dead afterwards anyway.
    4171              : 
    4172              :      (1) int tmp = a;
    4173              :          a = b;
    4174              :          b = tmp;
    4175              : 
    4176              :          ifcvt
    4177              :          -->
    4178              : 
    4179              :          tmp = a;
    4180              :          a = cond ? b : a_old;
    4181              :          b = cond ? tmp : b_old;
    4182              : 
    4183              :     Additionally, store the index of insns like (2) when a subsequent
    4184              :     SET reads from their destination.
    4185              : 
    4186              :     (2) int c = a;
    4187              :         int d = c;
    4188              : 
    4189              :         ifcvt
    4190              :         -->
    4191              : 
    4192              :         c = cond ? a : c_old;
    4193              :         d = cond ? d : c;     // Need to use c rather than c_old here.
    4194              : */
    4195              : 
    4196              : static void
    4197        30476 : init_noce_multiple_sets_info (basic_block bb,
    4198              :                      auto_delete_vec<noce_multiple_sets_info> &insn_info)
    4199              : {
    4200        30476 :   rtx_insn *insn;
    4201        30476 :   int count = 0;
    4202        30476 :   auto_vec<rtx> dests;
    4203        30476 :   bitmap bb_live_out = df_get_live_out (bb);
    4204              : 
    4205              :   /* Iterate over all SETs, storing the destinations in DEST.
    4206              :      - If we encounter a previously changed register,
    4207              :        rewire the read to the original source.
    4208              :      - If we encounter a SET that writes to a destination
    4209              :         that is not live after this block then the register
    4210              :         does not need to be moved conditionally.  */
    4211       190203 :   FOR_BB_INSNS (bb, insn)
    4212              :     {
    4213       159727 :       if (!active_insn_p (insn))
    4214        77169 :         continue;
    4215              : 
    4216        82558 :       noce_multiple_sets_info *info = new noce_multiple_sets_info;
    4217        82558 :       info->target = NULL_RTX;
    4218        82558 :       info->temporary = NULL_RTX;
    4219        82558 :       info->unmodified_insn = NULL;
    4220        82558 :       insn_info.safe_push (info);
    4221              : 
    4222        82558 :       rtx set = single_set (insn);
    4223        82558 :       gcc_checking_assert (set);
    4224              : 
    4225        82558 :       rtx src = SET_SRC (set);
    4226        82558 :       rtx dest = SET_DEST (set);
    4227              : 
    4228        82558 :       gcc_checking_assert (REG_P (dest));
    4229        82558 :       info->need_cmov = bitmap_bit_p (bb_live_out, REGNO (dest));
    4230              : 
    4231              :       /* Check if the current SET's source is the same
    4232              :          as any previously seen destination.
    4233              :          This is quadratic but the number of insns in BB
    4234              :          is bounded by PARAM_MAX_RTL_IF_CONVERSION_INSNS.  */
    4235       175798 :       for (int i = count - 1; i >= 0; --i)
    4236        93240 :         if (reg_mentioned_p (dests[i], src))
    4237        19661 :           insn_info[count]->rewired_src.safe_push (i);
    4238              : 
    4239        82558 :       dests.safe_push (dest);
    4240        82558 :       count++;
    4241              :     }
    4242        30476 : }
    4243              : 
    4244              : /* Return true iff basic block TEST_BB is suitable for conversion to a
    4245              :    series of conditional moves.  Also check that we have more than one
    4246              :    set (other routines can handle a single set better than we would),
    4247              :    and fewer than PARAM_MAX_RTL_IF_CONVERSION_INSNS sets.  While going
    4248              :    through the insns store the sum of their potential costs in COST.  */
    4249              : 
    4250              : static bool
    4251      1087465 : bb_ok_for_noce_convert_multiple_sets (basic_block test_bb, unsigned *cost)
    4252              : {
    4253      1087465 :   rtx_insn *insn;
    4254      1087465 :   unsigned count = 0;
    4255      1087465 :   unsigned param = param_max_rtl_if_conversion_insns;
    4256      1087465 :   bool speed_p = optimize_bb_for_speed_p (test_bb);
    4257      1087465 :   unsigned potential_cost = 0;
    4258              : 
    4259      9082241 :   FOR_BB_INSNS (test_bb, insn)
    4260              :     {
    4261              :       /* Skip over notes etc.  */
    4262      8966832 :       if (!active_insn_p (insn))
    4263      7046146 :         continue;
    4264              : 
    4265              :       /* We only handle SET insns.  */
    4266      1920686 :       rtx set = single_set (insn);
    4267      1920686 :       if (set == NULL_RTX)
    4268              :         return false;
    4269              : 
    4270      1705529 :       rtx dest = SET_DEST (set);
    4271      1705529 :       rtx src = SET_SRC (set);
    4272              : 
    4273              :       /* Do not handle anything involving memory loads/stores since it might
    4274              :          violate data-race-freedom guarantees.  Make sure we can force SRC
    4275              :          to a register as that may be needed in try_emit_cmove_seq.  */
    4276      1500775 :       if (!REG_P (dest) || contains_mem_rtx_p (src)
    4277      2713340 :           || !noce_can_force_operand (src))
    4278       721989 :         return false;
    4279              : 
    4280              :       /* Destination and source must be appropriate.  */
    4281       983540 :       if (!noce_operand_ok (dest) || !noce_operand_ok (src))
    4282         6003 :         return false;
    4283              : 
    4284              :       /* We must be able to conditionally move in this mode.  */
    4285       977537 :       if (!can_conditionally_move_p (GET_MODE (dest)))
    4286              :         return false;
    4287              : 
    4288       948630 :       potential_cost += insn_cost (insn, speed_p);
    4289              : 
    4290       948630 :       count++;
    4291              :     }
    4292              : 
    4293       115409 :   *cost += potential_cost;
    4294              : 
    4295              :   /* If we would only put out one conditional move, the other strategies
    4296              :      this pass tries are better optimized and will be more appropriate.
    4297              :      Some targets want to strictly limit the number of conditional moves
    4298              :      that are emitted, they set this through PARAM, we need to respect
    4299              :      that.  */
    4300       115409 :   return count > 1 && count <= param;
    4301              : }
    4302              : 
    4303              : /* Compute average of two given costs weighted by relative probabilities
    4304              :    of respective basic blocks in an IF-THEN-ELSE.  E is the IF-THEN edge.
    4305              :    With P as the probability to take the IF-THEN branch, return
    4306              :    P * THEN_COST + (1 - P) * ELSE_COST.  */
    4307              : static unsigned
    4308       258802 : average_cost (unsigned then_cost, unsigned else_cost, edge e)
    4309              : {
    4310       258802 :   return else_cost + e->probability.apply ((signed) (then_cost - else_cost));
    4311              : }
    4312              : 
    4313              : /* Given a simple IF-THEN-JOIN or IF-THEN-ELSE-JOIN block, attempt to convert
    4314              :    it without using conditional execution.  Return TRUE if we were successful
    4315              :    at converting the block.  */
    4316              : 
    4317              : static bool
    4318      1907948 : noce_process_if_block (struct noce_if_info *if_info)
    4319              : {
    4320      1907948 :   basic_block test_bb = if_info->test_bb;    /* test block */
    4321      1907948 :   basic_block then_bb = if_info->then_bb;    /* THEN */
    4322      1907948 :   basic_block else_bb = if_info->else_bb;    /* ELSE or NULL */
    4323      1907948 :   basic_block join_bb = if_info->join_bb;    /* JOIN */
    4324      1907948 :   rtx_insn *jump = if_info->jump;
    4325      1907948 :   rtx cond = if_info->cond;
    4326      1907948 :   rtx_insn *insn_a, *insn_b;
    4327      1907948 :   rtx set_a, set_b;
    4328      1907948 :   rtx orig_x, x, a, b;
    4329              : 
    4330              :   /* We're looking for patterns of the form
    4331              : 
    4332              :      (1) if (...) x = a; else x = b;
    4333              :      (2) x = b; if (...) x = a;
    4334              :      (3) if (...) x = a;   // as if with an initial x = x.
    4335              :      (4) if (...) { x = a; y = b; z = c; }  // Like 3, for multiple SETS.
    4336              :      The later patterns require jumps to be more expensive.
    4337              :      For the if (...) x = a; else x = b; case we allow multiple insns
    4338              :      inside the then and else blocks as long as their only effect is
    4339              :      to calculate a value for x.
    4340              :      ??? For future expansion, further expand the "multiple X" rules.  */
    4341              : 
    4342              :   /* First look for multiple SETS.
    4343              :      The original costs already include costs for the jump insn as well
    4344              :      as for a CC comparison if there is any.
    4345              :      If a target re-uses the existing CC comparison we keep track of that
    4346              :      and add the costs before default noce_conversion_profitable_p.  */
    4347              : 
    4348      1907948 :   unsigned potential_cost = if_info->original_cost;
    4349      1907948 :   unsigned old_cost = if_info->original_cost;
    4350      1907948 :   if (!else_bb
    4351              :       && HAVE_conditional_move
    4352      1907948 :       && bb_ok_for_noce_convert_multiple_sets (then_bb, &potential_cost))
    4353              :     {
    4354              :       /* Temporarily set the original costs to what we estimated so
    4355              :          we can determine if the transformation is worth it.  */
    4356        30476 :       if_info->original_cost = potential_cost;
    4357        30476 :       if (noce_convert_multiple_sets (if_info))
    4358              :         {
    4359        25492 :           if (dump_file && if_info->transform_name)
    4360            1 :             fprintf (dump_file, "if-conversion succeeded through %s\n",
    4361              :                      if_info->transform_name);
    4362        25492 :           return true;
    4363              :         }
    4364              : 
    4365              :       /* Restore the original costs.  */
    4366         4984 :       if_info->original_cost = old_cost;
    4367              :     }
    4368              : 
    4369      1882456 :   bool speed_p = optimize_bb_for_speed_p (test_bb);
    4370      1882456 :   unsigned int then_cost = 0, else_cost = 0;
    4371      1882456 :   if (!bb_valid_for_noce_process_p (then_bb, cond, &then_cost,
    4372              :                                     &if_info->then_simple))
    4373              :     return false;
    4374              : 
    4375       486755 :   if (else_bb
    4376       486755 :       && !bb_valid_for_noce_process_p (else_bb, cond, &else_cost,
    4377              :                                        &if_info->else_simple))
    4378              :     return false;
    4379              : 
    4380       301784 :   if (speed_p)
    4381       258802 :     if_info->original_cost += average_cost (then_cost, else_cost,
    4382              :                                             find_edge (test_bb, then_bb));
    4383              :   else
    4384        42982 :     if_info->original_cost += then_cost + else_cost;
    4385              : 
    4386       301784 :   insn_a = last_active_insn (then_bb, false);
    4387       301784 :   set_a = single_set (insn_a);
    4388       301784 :   gcc_assert (set_a);
    4389              : 
    4390       301784 :   x = SET_DEST (set_a);
    4391       301784 :   a = SET_SRC (set_a);
    4392              : 
    4393              :   /* Look for the other potential set.  Make sure we've got equivalent
    4394              :      destinations.  */
    4395              :   /* ??? This is overconservative.  Storing to two different mems is
    4396              :      as easy as conditionally computing the address.  Storing to a
    4397              :      single mem merely requires a scratch memory to use as one of the
    4398              :      destination addresses; often the memory immediately below the
    4399              :      stack pointer is available for this.  */
    4400       301784 :   set_b = NULL_RTX;
    4401       301784 :   if (else_bb)
    4402              :     {
    4403       105345 :       insn_b = last_active_insn (else_bb, false);
    4404       105345 :       set_b = single_set (insn_b);
    4405       105345 :       gcc_assert (set_b);
    4406              : 
    4407       105345 :       if (!rtx_interchangeable_p (x, SET_DEST (set_b)))
    4408              :         return false;
    4409              :     }
    4410              :   else
    4411              :     {
    4412       196439 :       insn_b = if_info->cond_earliest;
    4413       537289 :       do
    4414       537289 :         insn_b = prev_nonnote_nondebug_insn (insn_b);
    4415              :       while (insn_b
    4416       534579 :              && (BLOCK_FOR_INSN (insn_b)
    4417       534579 :                  == BLOCK_FOR_INSN (if_info->cond_earliest))
    4418      1183072 :              && !modified_in_p (x, insn_b));
    4419              : 
    4420              :       /* We're going to be moving the evaluation of B down from above
    4421              :          COND_EARLIEST to JUMP.  Make sure the relevant data is still
    4422              :          intact.  */
    4423       196439 :       if (! insn_b
    4424       193729 :           || BLOCK_FOR_INSN (insn_b) != BLOCK_FOR_INSN (if_info->cond_earliest)
    4425       108494 :           || !NONJUMP_INSN_P (insn_b)
    4426       103306 :           || (set_b = single_set (insn_b)) == NULL_RTX
    4427       101865 :           || ! rtx_interchangeable_p (x, SET_DEST (set_b))
    4428        87433 :           || ! noce_operand_ok (SET_SRC (set_b))
    4429        85473 :           || reg_overlap_mentioned_p (x, SET_SRC (set_b))
    4430        83547 :           || modified_between_p (SET_SRC (set_b), insn_b, jump)
    4431              :           /* Avoid extending the lifetime of hard registers on small
    4432              :              register class machines.  */
    4433        81110 :           || (REG_P (SET_SRC (set_b))
    4434        19407 :               && HARD_REGISTER_P (SET_SRC (set_b))
    4435         3329 :               && targetm.small_register_classes_for_mode_p
    4436         3329 :                    (GET_MODE (SET_SRC (set_b))))
    4437              :           /* Likewise with X.  In particular this can happen when
    4438              :              noce_get_condition looks farther back in the instruction
    4439              :              stream than one might expect.  */
    4440        77781 :           || reg_overlap_mentioned_p (x, cond)
    4441        64614 :           || reg_overlap_mentioned_p (x, a)
    4442       255206 :           || modified_between_p (x, insn_b, jump))
    4443              :         {
    4444              :           insn_b = NULL;
    4445              :           set_b = NULL_RTX;
    4446              :         }
    4447              :     }
    4448              : 
    4449              :   /* If x has side effects then only the if-then-else form is safe to
    4450              :      convert.  But even in that case we would need to restore any notes
    4451              :      (such as REG_INC) at then end.  That can be tricky if
    4452              :      noce_emit_move_insn expands to more than one insn, so disable the
    4453              :      optimization entirely for now if there are side effects.  */
    4454       290134 :   if (side_effects_p (x))
    4455              :     return false;
    4456              : 
    4457       290134 :   b = (set_b ? SET_SRC (set_b) : x);
    4458              : 
    4459              :   /* Only operate on register destinations, and even then avoid extending
    4460              :      the lifetime of hard registers on small register class machines.  */
    4461       290134 :   orig_x = x;
    4462       290134 :   if_info->orig_x = orig_x;
    4463       290134 :   if (!REG_P (x)
    4464       290134 :       || (HARD_REGISTER_P (x)
    4465            2 :           && targetm.small_register_classes_for_mode_p (GET_MODE (x))))
    4466              :     {
    4467        67169 :       if (GET_MODE (x) == BLKmode)
    4468              :         return false;
    4469              : 
    4470        66933 :       if (GET_CODE (x) == ZERO_EXTRACT
    4471            2 :           && (!CONST_INT_P (XEXP (x, 1))
    4472            2 :               || !CONST_INT_P (XEXP (x, 2))))
    4473              :         return false;
    4474              : 
    4475        66933 :       x = gen_reg_rtx (GET_MODE (GET_CODE (x) == STRICT_LOW_PART
    4476              :                                  ? XEXP (x, 0) : x));
    4477              :     }
    4478              : 
    4479              :   /* Don't operate on sources that may trap or are volatile.  */
    4480       289898 :   if (! noce_operand_ok (a) || ! noce_operand_ok (b))
    4481            0 :     return false;
    4482              : 
    4483       317335 :  retry:
    4484              :   /* Set up the info block for our subroutines.  */
    4485       317335 :   if_info->insn_a = insn_a;
    4486       317335 :   if_info->insn_b = insn_b;
    4487       317335 :   if_info->x = x;
    4488       317335 :   if_info->a = a;
    4489       317335 :   if_info->b = b;
    4490              : 
    4491              :   /* Try optimizations in some approximation of a useful order.  */
    4492              :   /* ??? Should first look to see if X is live incoming at all.  If it
    4493              :      isn't, we don't need anything but an unconditional set.  */
    4494              : 
    4495              :   /* Look and see if A and B are really the same.  Avoid creating silly
    4496              :      cmove constructs that no one will fix up later.  */
    4497       317335 :   if (noce_simple_bbs (if_info)
    4498       295352 :       && rtx_interchangeable_p (a, b))
    4499              :     {
    4500              :       /* If we have an INSN_B, we don't have to create any new rtl.  Just
    4501              :          move the instruction that we already have.  If we don't have an
    4502              :          INSN_B, that means that A == X, and we've got a noop move.  In
    4503              :          that case don't do anything and let the code below delete INSN_A.  */
    4504          388 :       if (insn_b && else_bb)
    4505              :         {
    4506          377 :           rtx note;
    4507              : 
    4508          377 :           if (else_bb && insn_b == BB_END (else_bb))
    4509          258 :             BB_END (else_bb) = PREV_INSN (insn_b);
    4510          377 :           reorder_insns (insn_b, insn_b, PREV_INSN (jump));
    4511              : 
    4512              :           /* If there was a REG_EQUAL note, delete it since it may have been
    4513              :              true due to this insn being after a jump.  */
    4514          377 :           if ((note = find_reg_note (insn_b, REG_EQUAL, NULL_RTX)) != 0)
    4515            0 :             remove_note (insn_b, note);
    4516              : 
    4517          388 :           insn_b = NULL;
    4518              :         }
    4519              :       /* If we have "x = b; if (...) x = a;", and x has side-effects, then
    4520              :          x must be executed twice.  */
    4521           11 :       else if (insn_b && side_effects_p (orig_x))
    4522              :         return false;
    4523              : 
    4524          388 :       x = orig_x;
    4525          388 :       goto success;
    4526              :     }
    4527              : 
    4528       316947 :   if (!set_b && MEM_P (orig_x))
    4529              :     /* We want to avoid store speculation to avoid cases like
    4530              :          if (pthread_mutex_trylock(mutex))
    4531              :            ++global_variable;
    4532              :        Rather than go to much effort here, we rely on the SSA optimizers,
    4533              :        which do a good enough job these days.  */
    4534              :     return false;
    4535              : 
    4536       251585 :   if (noce_try_move (if_info))
    4537            0 :     goto success;
    4538       251585 :   if (noce_try_ifelse_collapse (if_info))
    4539        15681 :     goto success;
    4540       235904 :   if (noce_try_store_flag (if_info))
    4541        26017 :     goto success;
    4542       209887 :   if (noce_try_bitop (if_info))
    4543            0 :     goto success;
    4544       209887 :   if (noce_try_minmax (if_info))
    4545           52 :     goto success;
    4546       209835 :   if (noce_try_abs (if_info))
    4547           24 :     goto success;
    4548       209811 :   if (noce_try_inverse_constants (if_info))
    4549            0 :     goto success;
    4550       209811 :   if (!targetm.have_conditional_execution ()
    4551       209811 :       && noce_try_store_flag_constants (if_info))
    4552         3166 :     goto success;
    4553       206645 :   if (noce_try_sign_bit_splat (if_info))
    4554          174 :     goto success;
    4555       206471 :   if (!targetm.have_conditional_execution ()
    4556       206471 :       && noce_try_store_flag_logical (if_info))
    4557            0 :     goto success;
    4558       206471 :   if (HAVE_conditional_move
    4559       206471 :       && noce_try_cmove (if_info))
    4560        41877 :     goto success;
    4561       164594 :   if (! targetm.have_conditional_execution ())
    4562              :     {
    4563       164594 :       if (noce_try_addcc (if_info))
    4564         5040 :         goto success;
    4565       159554 :       if (noce_try_store_flag_mask (if_info))
    4566           11 :         goto success;
    4567       159543 :       if (HAVE_conditional_move
    4568       159543 :           && noce_try_cond_arith (if_info))
    4569         8561 :         goto success;
    4570       150982 :       if (HAVE_conditional_move
    4571       150982 :           && noce_try_cmove_arith (if_info))
    4572        38091 :         goto success;
    4573       112891 :       if (noce_try_sign_mask (if_info))
    4574            0 :         goto success;
    4575              :     }
    4576              : 
    4577       112891 :   if (!else_bb && set_b)
    4578              :     {
    4579        27437 :       insn_b = NULL;
    4580        27437 :       set_b = NULL_RTX;
    4581        27437 :       b = orig_x;
    4582        27437 :       goto retry;
    4583              :     }
    4584              : 
    4585              :   return false;
    4586              : 
    4587       139082 :  success:
    4588       139082 :   if (dump_file && if_info->transform_name)
    4589            5 :     fprintf (dump_file, "if-conversion succeeded through %s\n",
    4590              :              if_info->transform_name);
    4591              : 
    4592              :   /* If we used a temporary, fix it up now.  */
    4593       139082 :   if (orig_x != x)
    4594              :     {
    4595          693 :       rtx_insn *seq;
    4596              : 
    4597          693 :       start_sequence ();
    4598          693 :       noce_emit_move_insn (orig_x, x);
    4599          693 :       seq = get_insns ();
    4600          693 :       set_used_flags (orig_x);
    4601          693 :       unshare_all_rtl_in_chain (seq);
    4602          693 :       end_sequence ();
    4603              : 
    4604          693 :       emit_insn_before_setloc (seq, BB_END (test_bb), INSN_LOCATION (insn_a));
    4605              :     }
    4606              : 
    4607              :   /* The original THEN and ELSE blocks may now be removed.  The test block
    4608              :      must now jump to the join block.  If the test block and the join block
    4609              :      can be merged, do so.  */
    4610       139082 :   if (else_bb)
    4611              :     {
    4612        64702 :       delete_basic_block (else_bb);
    4613        64702 :       num_true_changes++;
    4614              :     }
    4615              :   else
    4616        74380 :     remove_edge (find_edge (test_bb, join_bb));
    4617              : 
    4618       139082 :   remove_edge (find_edge (then_bb, join_bb));
    4619       139082 :   redirect_edge_and_branch_force (single_succ_edge (test_bb), join_bb);
    4620       139082 :   delete_basic_block (then_bb);
    4621       139082 :   num_true_changes++;
    4622              : 
    4623       139082 :   if (can_merge_blocks_p (test_bb, join_bb))
    4624              :     {
    4625       109237 :       merge_blocks (test_bb, join_bb);
    4626       109237 :       num_true_changes++;
    4627              :     }
    4628              : 
    4629       139082 :   num_updated_if_blocks++;
    4630       139082 :   return true;
    4631              : }
    4632              : 
    4633              : /* Check whether a block is suitable for conditional move conversion.
    4634              :    Every insn must be a simple set of a register to a constant or a
    4635              :    register.  For each assignment, store the value in the pointer map
    4636              :    VALS, keyed indexed by register pointer, then store the register
    4637              :    pointer in REGS.  COND is the condition we will test.  */
    4638              : 
    4639              : static bool
    4640      1773953 : check_cond_move_block (basic_block bb,
    4641              :                        hash_map<rtx, rtx> *vals,
    4642              :                        vec<rtx> *regs,
    4643              :                        rtx cond)
    4644              : {
    4645      1773953 :   rtx_insn *insn;
    4646      1773953 :   rtx cc = cc_in_cond (cond);
    4647              : 
    4648              :    /* We can only handle simple jumps at the end of the basic block.
    4649              :       It is almost impossible to update the CFG otherwise.  */
    4650      1773953 :   insn = BB_END (bb);
    4651      1773953 :   if (JUMP_P (insn) && !onlyjump_p (insn))
    4652              :     return false;
    4653              : 
    4654     10365697 :   FOR_BB_INSNS (bb, insn)
    4655              :     {
    4656     10303290 :       rtx set, dest, src;
    4657              : 
    4658     10303290 :       if (!NONDEBUG_INSN_P (insn) || JUMP_P (insn))
    4659      8460674 :         continue;
    4660      1842616 :       set = single_set (insn);
    4661      1842616 :       if (!set)
    4662      1711493 :         return false;
    4663              : 
    4664      1768910 :       dest = SET_DEST (set);
    4665      1768910 :       src = SET_SRC (set);
    4666      1768910 :       if (!REG_P (dest)
    4667      1768910 :           || (HARD_REGISTER_P (dest)
    4668       289555 :               && targetm.small_register_classes_for_mode_p (GET_MODE (dest))))
    4669       676916 :         return false;
    4670              : 
    4671      1091994 :       if (!CONSTANT_P (src) && !register_operand (src, VOIDmode))
    4672              :         return false;
    4673              : 
    4674       153737 :       if (side_effects_p (src) || side_effects_p (dest))
    4675            0 :         return false;
    4676              : 
    4677       153737 :       if (may_trap_p (src) || may_trap_p (dest))
    4678            0 :         return false;
    4679              : 
    4680              :       /* Don't try to handle this if the source register was
    4681              :          modified earlier in the block.  */
    4682       153737 :       if ((REG_P (src)
    4683        50754 :            && vals->get (src))
    4684       204238 :           || (GET_CODE (src) == SUBREG && REG_P (SUBREG_REG (src))
    4685         5165 :               && vals->get (SUBREG_REG (src))))
    4686          305 :         return false;
    4687              : 
    4688              :       /* Don't try to handle this if the destination register was
    4689              :          modified earlier in the block.  */
    4690       153432 :       if (vals->get (dest))
    4691              :         return false;
    4692              : 
    4693              :       /* Don't try to handle this if the condition uses the
    4694              :          destination register.  */
    4695       153432 :       if (reg_overlap_mentioned_p (dest, cond))
    4696              :         return false;
    4697              : 
    4698              :       /* Don't try to handle this if the source register is modified
    4699              :          later in the block.  */
    4700       134400 :       if (!CONSTANT_P (src)
    4701       134400 :           && modified_between_p (src, insn, NEXT_INSN (BB_END (bb))))
    4702              :         return false;
    4703              : 
    4704              :       /* Skip it if the instruction to be moved might clobber CC.  */
    4705       131123 :       if (cc && set_of (cc, insn))
    4706              :         return false;
    4707              : 
    4708       131123 :       vals->put (dest, src);
    4709              : 
    4710       131123 :       regs->safe_push (dest);
    4711              :     }
    4712              : 
    4713              :   return true;
    4714              : }
    4715              : 
    4716              : /* Given a basic block BB suitable for conditional move conversion,
    4717              :    a condition COND, and pointer maps THEN_VALS and ELSE_VALS containing
    4718              :    the register values depending on COND, emit the insns in the block as
    4719              :    conditional moves.  If ELSE_BLOCK is true, THEN_BB was already
    4720              :    processed.  The caller has started a sequence for the conversion.
    4721              :    Return true if successful, false if something goes wrong.  */
    4722              : 
    4723              : static bool
    4724        36915 : cond_move_convert_if_block (struct noce_if_info *if_infop,
    4725              :                             basic_block bb, rtx cond,
    4726              :                             hash_map<rtx, rtx> *then_vals,
    4727              :                             hash_map<rtx, rtx> *else_vals,
    4728              :                             bool else_block_p)
    4729              : {
    4730        36915 :   enum rtx_code code;
    4731        36915 :   rtx_insn *insn;
    4732        36915 :   rtx cond_arg0, cond_arg1;
    4733              : 
    4734        36915 :   code = GET_CODE (cond);
    4735        36915 :   cond_arg0 = XEXP (cond, 0);
    4736        36915 :   cond_arg1 = XEXP (cond, 1);
    4737              : 
    4738       127579 :   FOR_BB_INSNS (bb, insn)
    4739              :     {
    4740       105025 :       rtx set, target, dest, t, e;
    4741              : 
    4742              :       /* ??? Maybe emit conditional debug insn?  */
    4743       105025 :       if (!NONDEBUG_INSN_P (insn) || JUMP_P (insn))
    4744        69283 :         continue;
    4745        46974 :       set = single_set (insn);
    4746        46974 :       gcc_assert (set && REG_P (SET_DEST (set)));
    4747              : 
    4748        46974 :       dest = SET_DEST (set);
    4749              : 
    4750        46974 :       rtx *then_slot = then_vals->get (dest);
    4751        46974 :       rtx *else_slot = else_vals->get (dest);
    4752        46974 :       t = then_slot ? *then_slot : NULL_RTX;
    4753        46974 :       e = else_slot ? *else_slot : NULL_RTX;
    4754              : 
    4755        46974 :       if (else_block_p)
    4756              :         {
    4757              :           /* If this register was set in the then block, we already
    4758              :              handled this case there.  */
    4759        12630 :           if (t)
    4760        11232 :             continue;
    4761         1398 :           t = dest;
    4762         1398 :           gcc_assert (e);
    4763              :         }
    4764              :       else
    4765              :         {
    4766        34344 :           gcc_assert (t);
    4767        34344 :           if (!e)
    4768        22441 :             e = dest;
    4769              :         }
    4770              : 
    4771        35742 :       if (if_infop->cond_inverted)
    4772            0 :         std::swap (t, e);
    4773              : 
    4774        35742 :       target = noce_emit_cmove (if_infop, dest, code, cond_arg0, cond_arg1,
    4775              :                                 t, e);
    4776        35742 :       if (!target)
    4777        14361 :         return false;
    4778              : 
    4779        21381 :       if (target != dest)
    4780            0 :         noce_emit_move_insn (dest, target);
    4781              :     }
    4782              : 
    4783              :   return true;
    4784              : }
    4785              : 
    4786              : /* Given a simple IF-THEN-JOIN or IF-THEN-ELSE-JOIN block, attempt to convert
    4787              :    it using only conditional moves.  Return TRUE if we were successful at
    4788              :    converting the block.  */
    4789              : 
    4790              : static bool
    4791      1743374 : cond_move_process_if_block (struct noce_if_info *if_info)
    4792              : {
    4793      1743374 :   basic_block test_bb = if_info->test_bb;
    4794      1743374 :   basic_block then_bb = if_info->then_bb;
    4795      1743374 :   basic_block else_bb = if_info->else_bb;
    4796      1743374 :   basic_block join_bb = if_info->join_bb;
    4797      1743374 :   rtx_insn *jump = if_info->jump;
    4798      1743374 :   rtx cond = if_info->cond;
    4799      1743374 :   rtx_insn *seq, *loc_insn;
    4800      1743374 :   int c;
    4801      1743374 :   vec<rtx> then_regs = vNULL;
    4802      1743374 :   vec<rtx> else_regs = vNULL;
    4803      1743374 :   bool success_p = false;
    4804      1743374 :   int limit = param_max_rtl_if_conversion_insns;
    4805              : 
    4806              :   /* Build a mapping for each block to the value used for each
    4807              :      register.  */
    4808      1743374 :   hash_map<rtx, rtx> then_vals;
    4809      1743374 :   hash_map<rtx, rtx> else_vals;
    4810              : 
    4811              :   /* Make sure the blocks are suitable.  */
    4812      1743374 :   if (!check_cond_move_block (then_bb, &then_vals, &then_regs, cond)
    4813      1743374 :       || (else_bb
    4814        30579 :           && !check_cond_move_block (else_bb, &else_vals, &else_regs, cond)))
    4815      1711546 :     goto done;
    4816              : 
    4817              :   /* Make sure the blocks can be used together.  If the same register
    4818              :      is set in both blocks, and is not set to a constant in both
    4819              :      cases, then both blocks must set it to the same register.  We
    4820              :      have already verified that if it is set to a register, that the
    4821              :      source register does not change after the assignment.  Also count
    4822              :      the number of registers set in only one of the blocks.  */
    4823        31828 :   c = 0;
    4824       130902 :   for (rtx reg : then_regs)
    4825              :     {
    4826        38371 :       rtx *then_slot = then_vals.get (reg);
    4827        38371 :       rtx *else_slot = else_vals.get (reg);
    4828              : 
    4829        38371 :       gcc_checking_assert (then_slot);
    4830        38371 :       if (!else_slot)
    4831        23166 :         ++c;
    4832              :       else
    4833              :         {
    4834        15205 :           rtx then_val = *then_slot;
    4835        15205 :           rtx else_val = *else_slot;
    4836         4174 :           if (!CONSTANT_P (then_val) && !CONSTANT_P (else_val)
    4837        18738 :               && !rtx_equal_p (then_val, else_val))
    4838         2655 :             goto done;
    4839              :         }
    4840              :     }
    4841              : 
    4842              :   /* Finish off c for MAX_CONDITIONAL_EXECUTE.  */
    4843        60076 :   for (rtx reg : else_regs)
    4844              :     {
    4845        13933 :       gcc_checking_assert (else_vals.get (reg));
    4846        13933 :       if (!then_vals.get (reg))
    4847         1530 :         ++c;
    4848              :     }
    4849              : 
    4850              :   /* Make sure it is reasonable to convert this block.  What matters
    4851              :      is the number of assignments currently made in only one of the
    4852              :      branches, since if we convert we are going to always execute
    4853              :      them.  */
    4854        29173 :   if (c > MAX_CONDITIONAL_EXECUTE
    4855        29173 :       || c > limit)
    4856           38 :     goto done;
    4857              : 
    4858              :   /* Try to emit the conditional moves.  First do the then block,
    4859              :      then do anything left in the else blocks.  */
    4860        29135 :   start_sequence ();
    4861        29135 :   if (!cond_move_convert_if_block (if_info, then_bb, cond,
    4862              :                                    &then_vals, &else_vals, false)
    4863        29135 :       || (else_bb
    4864         7780 :           && !cond_move_convert_if_block (if_info, else_bb, cond,
    4865              :                                           &then_vals, &else_vals, true)))
    4866              :     {
    4867        14361 :       end_sequence ();
    4868        14361 :       goto done;
    4869              :     }
    4870        14774 :   seq = end_ifcvt_sequence (if_info);
    4871        14774 :   if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
    4872        11699 :     goto done;
    4873              : 
    4874         3075 :   loc_insn = first_active_insn (then_bb);
    4875         3075 :   if (!loc_insn)
    4876              :     {
    4877            0 :       loc_insn = first_active_insn (else_bb);
    4878            0 :       gcc_assert (loc_insn);
    4879              :     }
    4880         3075 :   emit_insn_before_setloc (seq, jump, INSN_LOCATION (loc_insn));
    4881              : 
    4882         3075 :   if (else_bb)
    4883              :     {
    4884         3075 :       delete_basic_block (else_bb);
    4885         3075 :       num_true_changes++;
    4886              :     }
    4887              :   else
    4888            0 :     remove_edge (find_edge (test_bb, join_bb));
    4889              : 
    4890         3075 :   remove_edge (find_edge (then_bb, join_bb));
    4891         3075 :   redirect_edge_and_branch_force (single_succ_edge (test_bb), join_bb);
    4892         3075 :   delete_basic_block (then_bb);
    4893         3075 :   num_true_changes++;
    4894              : 
    4895         3075 :   if (can_merge_blocks_p (test_bb, join_bb))
    4896              :     {
    4897         1293 :       merge_blocks (test_bb, join_bb);
    4898         1293 :       num_true_changes++;
    4899              :     }
    4900              : 
    4901         3075 :   num_updated_if_blocks++;
    4902         3075 :   success_p = true;
    4903              : 
    4904      1743374 : done:
    4905      1743374 :   then_regs.release ();
    4906      1743374 :   else_regs.release ();
    4907      1743374 :   return success_p;
    4908      1743374 : }
    4909              : 
    4910              : 
    4911              : /* Determine if a given basic block heads a simple IF-THEN-JOIN or an
    4912              :    IF-THEN-ELSE-JOIN block.
    4913              : 
    4914              :    If so, we'll try to convert the insns to not require the branch,
    4915              :    using only transformations that do not require conditional execution.
    4916              : 
    4917              :    Return TRUE if we were successful at converting the block.  */
    4918              : 
    4919              : static bool
    4920      9885913 : noce_find_if_block (basic_block test_bb, edge then_edge, edge else_edge,
    4921              :                     int pass)
    4922              : {
    4923      9885913 :   basic_block then_bb, else_bb, join_bb;
    4924      9885913 :   bool then_else_reversed = false;
    4925      9885913 :   rtx_insn *jump;
    4926      9885913 :   rtx_insn *cond_earliest;
    4927      9885913 :   struct noce_if_info if_info;
    4928      9885913 :   bool speed_p = optimize_bb_for_speed_p (test_bb);
    4929              : 
    4930              :   /* We only ever should get here before reload.  */
    4931      9885913 :   gcc_assert (!reload_completed);
    4932              : 
    4933              :   /* Recognize an IF-THEN-ELSE-JOIN block.  */
    4934      9885913 :   if (single_pred_p (then_edge->dest)
    4935      8134158 :       && single_succ_p (then_edge->dest)
    4936      3554446 :       && single_pred_p (else_edge->dest)
    4937     10157408 :       && single_succ_p (else_edge->dest)
    4938     11043437 :       && single_succ (then_edge->dest) == single_succ (else_edge->dest))
    4939              :     {
    4940              :       then_bb = then_edge->dest;
    4941              :       else_bb = else_edge->dest;
    4942              :       join_bb = single_succ (then_bb);
    4943              :     }
    4944              :   /* Recognize an IF-THEN-JOIN block.  */
    4945      8999884 :   else if (single_pred_p (then_edge->dest)
    4946     10709014 :            && single_succ_p (then_edge->dest)
    4947     11668301 :            && single_succ (then_edge->dest) == else_edge->dest)
    4948              :     {
    4949              :       then_bb = then_edge->dest;
    4950              :       else_bb = NULL_BLOCK;
    4951              :       join_bb = else_edge->dest;
    4952              :     }
    4953              :   /* Recognize an IF-ELSE-JOIN block.  We can have those because the order
    4954              :      of basic blocks in cfglayout mode does not matter, so the fallthrough
    4955              :      edge can go to any basic block (and not just to bb->next_bb, like in
    4956              :      cfgrtl mode).  */
    4957     17758861 :   else if (single_pred_p (else_edge->dest)
    4958     11110331 :            && single_succ_p (else_edge->dest)
    4959      9432664 :            && single_succ (else_edge->dest) == then_edge->dest)
    4960              :     {
    4961              :       /* The noce transformations do not apply to IF-ELSE-JOIN blocks.
    4962              :          To make this work, we have to invert the THEN and ELSE blocks
    4963              :          and reverse the jump condition.  */
    4964              :       then_bb = else_edge->dest;
    4965              :       else_bb = NULL_BLOCK;
    4966              :       join_bb = single_succ (then_bb);
    4967              :       then_else_reversed = true;
    4968              :     }
    4969              :   else
    4970              :     /* Not a form we can handle.  */
    4971              :     return false;
    4972              : 
    4973              :   /* The edges of the THEN and ELSE blocks cannot have complex edges.  */
    4974      1977019 :   if (single_succ_edge (then_bb)->flags & EDGE_COMPLEX)
    4975              :     return false;
    4976      1921917 :   if (else_bb
    4977      1921917 :       && single_succ_edge (else_bb)->flags & EDGE_COMPLEX)
    4978              :     return false;
    4979              : 
    4980      1911820 :   num_possible_if_blocks++;
    4981              : 
    4982      1911820 :   if (dump_file)
    4983              :     {
    4984           90 :       fprintf (dump_file,
    4985              :                "\nIF-THEN%s-JOIN block found, pass %d, test %d, then %d",
    4986              :                (else_bb) ? "-ELSE" : "",
    4987              :                pass, test_bb->index, then_bb->index);
    4988              : 
    4989           53 :       if (else_bb)
    4990           16 :         fprintf (dump_file, ", else %d", else_bb->index);
    4991              : 
    4992           53 :       fprintf (dump_file, ", join %d\n", join_bb->index);
    4993              :     }
    4994              : 
    4995              :   /* If the conditional jump is more than just a conditional
    4996              :      jump, then we cannot do if-conversion on this block.  */
    4997      1911820 :   jump = BB_END (test_bb);
    4998      1911820 :   if (! onlyjump_p (jump))
    4999              :     return false;
    5000              : 
    5001              :   /* Initialize an IF_INFO struct to pass around.  */
    5002      1911587 :   memset (&if_info, 0, sizeof if_info);
    5003      1911587 :   if_info.test_bb = test_bb;
    5004      1911587 :   if_info.then_bb = then_bb;
    5005      1911587 :   if_info.else_bb = else_bb;
    5006      1911587 :   if_info.join_bb = join_bb;
    5007      1911587 :   if_info.cond = noce_get_condition (jump, &cond_earliest,
    5008              :                                      then_else_reversed);
    5009      1911587 :   rtx_insn *rev_cond_earliest;
    5010      3823174 :   if_info.rev_cond = noce_get_condition (jump, &rev_cond_earliest,
    5011      1911587 :                                          !then_else_reversed);
    5012      1911587 :   if (!if_info.cond && !if_info.rev_cond)
    5013              :     return false;
    5014      1907948 :   if (!if_info.cond)
    5015              :     {
    5016            0 :       std::swap (if_info.cond, if_info.rev_cond);
    5017            0 :       std::swap (cond_earliest, rev_cond_earliest);
    5018            0 :       if_info.cond_inverted = true;
    5019              :     }
    5020              :   /* We must be comparing objects whose modes imply the size.  */
    5021      1907948 :   if (GET_MODE (XEXP (if_info.cond, 0)) == BLKmode)
    5022              :     return false;
    5023      1907948 :   gcc_assert (if_info.rev_cond == NULL_RTX
    5024              :               || rev_cond_earliest == cond_earliest);
    5025      1907948 :   if_info.cond_earliest = cond_earliest;
    5026      1907948 :   if_info.jump = jump;
    5027      1907948 :   if_info.then_else_reversed = then_else_reversed;
    5028      1907948 :   if_info.speed_p = speed_p;
    5029      1907948 :   if_info.max_seq_cost
    5030      1907948 :     = targetm.max_noce_ifcvt_seq_cost (then_edge);
    5031              :   /* We'll add in the cost of THEN_BB and ELSE_BB later, when we check
    5032              :      that they are valid to transform.  We can't easily get back to the insn
    5033              :      for COND (and it may not exist if we had to canonicalize to get COND).
    5034              :      It is assumed that the costs of a jump insn are dependent on the
    5035              :      branch costs.  */
    5036      1907948 :   if_info.original_cost += insn_cost (if_info.jump, if_info.speed_p);
    5037              : 
    5038              :   /* Do the real work.  */
    5039              : 
    5040              :   /* ??? noce_process_if_block has not yet been updated to handle
    5041              :      inverted conditions.  */
    5042      1907948 :   if (!if_info.cond_inverted && noce_process_if_block (&if_info))
    5043              :     return true;
    5044              : 
    5045      1743374 :   if (HAVE_conditional_move
    5046      1743374 :       && cond_move_process_if_block (&if_info))
    5047              :     return true;
    5048              : 
    5049              :   return false;
    5050              : }
    5051              : 
    5052              : 
    5053              : /* Merge the blocks and mark for local life update.  */
    5054              : 
    5055              : static void
    5056            0 : merge_if_block (struct ce_if_block * ce_info)
    5057              : {
    5058            0 :   basic_block test_bb = ce_info->test_bb;    /* last test block */
    5059            0 :   basic_block then_bb = ce_info->then_bb;    /* THEN */
    5060            0 :   basic_block else_bb = ce_info->else_bb;    /* ELSE or NULL */
    5061            0 :   basic_block join_bb = ce_info->join_bb;    /* join block */
    5062            0 :   basic_block combo_bb;
    5063              : 
    5064              :   /* All block merging is done into the lower block numbers.  */
    5065              : 
    5066            0 :   combo_bb = test_bb;
    5067            0 :   df_set_bb_dirty (test_bb);
    5068              : 
    5069              :   /* Merge any basic blocks to handle && and || subtests.  Each of
    5070              :      the blocks are on the fallthru path from the predecessor block.  */
    5071            0 :   if (ce_info->num_multiple_test_blocks > 0)
    5072              :     {
    5073            0 :       basic_block bb = test_bb;
    5074            0 :       basic_block last_test_bb = ce_info->last_test_bb;
    5075            0 :       basic_block fallthru = block_fallthru (bb);
    5076              : 
    5077            0 :       do
    5078              :         {
    5079            0 :           bb = fallthru;
    5080            0 :           fallthru = block_fallthru (bb);
    5081            0 :           merge_blocks (combo_bb, bb);
    5082            0 :           num_true_changes++;
    5083              :         }
    5084            0 :       while (bb != last_test_bb);
    5085              :     }
    5086              : 
    5087              :   /* Merge TEST block into THEN block.  Normally the THEN block won't have a
    5088              :      label, but it might if there were || tests.  That label's count should be
    5089              :      zero, and it normally should be removed.  */
    5090              : 
    5091            0 :   if (then_bb)
    5092              :     {
    5093              :       /* If THEN_BB has no successors, then there's a BARRIER after it.
    5094              :          If COMBO_BB has more than one successor (THEN_BB), then that BARRIER
    5095              :          is no longer needed, and in fact it is incorrect to leave it in
    5096              :          the insn stream.  */
    5097            0 :       if (EDGE_COUNT (then_bb->succs) == 0
    5098            0 :           && EDGE_COUNT (combo_bb->succs) > 1)
    5099              :         {
    5100            0 :           rtx_insn *end = NEXT_INSN (BB_END (then_bb));
    5101            0 :           while (end && NOTE_P (end) && !NOTE_INSN_BASIC_BLOCK_P (end))
    5102            0 :             end = NEXT_INSN (end);
    5103              : 
    5104            0 :           if (end && BARRIER_P (end))
    5105            0 :             delete_insn (end);
    5106              :         }
    5107            0 :       merge_blocks (combo_bb, then_bb);
    5108            0 :       num_true_changes++;
    5109              :     }
    5110              : 
    5111              :   /* The ELSE block, if it existed, had a label.  That label count
    5112              :      will almost always be zero, but odd things can happen when labels
    5113              :      get their addresses taken.  */
    5114            0 :   if (else_bb)
    5115              :     {
    5116              :       /* If ELSE_BB has no successors, then there's a BARRIER after it.
    5117              :          If COMBO_BB has more than one successor (ELSE_BB), then that BARRIER
    5118              :          is no longer needed, and in fact it is incorrect to leave it in
    5119              :          the insn stream.  */
    5120            0 :       if (EDGE_COUNT (else_bb->succs) == 0
    5121            0 :           && EDGE_COUNT (combo_bb->succs) > 1)
    5122              :         {
    5123            0 :           rtx_insn *end = NEXT_INSN (BB_END (else_bb));
    5124            0 :           while (end && NOTE_P (end) && !NOTE_INSN_BASIC_BLOCK_P (end))
    5125            0 :             end = NEXT_INSN (end);
    5126              : 
    5127            0 :           if (end && BARRIER_P (end))
    5128            0 :             delete_insn (end);
    5129              :         }
    5130            0 :       merge_blocks (combo_bb, else_bb);
    5131            0 :       num_true_changes++;
    5132              :     }
    5133              : 
    5134              :   /* If there was no join block reported, that means it was not adjacent
    5135              :      to the others, and so we cannot merge them.  */
    5136              : 
    5137            0 :   if (! join_bb)
    5138              :     {
    5139            0 :       rtx_insn *last = BB_END (combo_bb);
    5140              : 
    5141              :       /* The outgoing edge for the current COMBO block should already
    5142              :          be correct.  Verify this.  */
    5143            0 :       if (EDGE_COUNT (combo_bb->succs) == 0)
    5144            0 :         gcc_assert (find_reg_note (last, REG_NORETURN, NULL)
    5145              :                     || (NONJUMP_INSN_P (last)
    5146              :                         && GET_CODE (PATTERN (last)) == TRAP_IF
    5147              :                         && (TRAP_CONDITION (PATTERN (last))
    5148              :                             == const_true_rtx)));
    5149              : 
    5150              :       else
    5151              :       /* There should still be something at the end of the THEN or ELSE
    5152              :          blocks taking us to our final destination.  */
    5153            0 :         gcc_assert (JUMP_P (last)
    5154              :                     || (EDGE_SUCC (combo_bb, 0)->dest
    5155              :                         == EXIT_BLOCK_PTR_FOR_FN (cfun)
    5156              :                         && CALL_P (last)
    5157              :                         && SIBLING_CALL_P (last))
    5158              :                     || ((EDGE_SUCC (combo_bb, 0)->flags & EDGE_EH)
    5159              :                         && can_throw_internal (last)));
    5160              :     }
    5161              : 
    5162              :   /* The JOIN block may have had quite a number of other predecessors too.
    5163              :      Since we've already merged the TEST, THEN and ELSE blocks, we should
    5164              :      have only one remaining edge from our if-then-else diamond.  If there
    5165              :      is more than one remaining edge, it must come from elsewhere.  There
    5166              :      may be zero incoming edges if the THEN block didn't actually join
    5167              :      back up (as with a call to a non-return function).  */
    5168            0 :   else if (EDGE_COUNT (join_bb->preds) < 2
    5169            0 :            && join_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
    5170              :     {
    5171              :       /* We can merge the JOIN cleanly and update the dataflow try
    5172              :          again on this pass.*/
    5173            0 :       merge_blocks (combo_bb, join_bb);
    5174            0 :       num_true_changes++;
    5175              :     }
    5176              :   else
    5177              :     {
    5178              :       /* We cannot merge the JOIN.  */
    5179              : 
    5180              :       /* The outgoing edge for the current COMBO block should already
    5181              :          be correct.  Verify this.  */
    5182            0 :       gcc_assert (single_succ_p (combo_bb)
    5183              :                   && single_succ (combo_bb) == join_bb);
    5184              : 
    5185              :       /* Remove the jump and cruft from the end of the COMBO block.  */
    5186            0 :       if (join_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
    5187            0 :         tidy_fallthru_edge (single_succ_edge (combo_bb));
    5188              :     }
    5189              : 
    5190            0 :   num_updated_if_blocks++;
    5191            0 : }
    5192              : 
    5193              : /* Find a block ending in a simple IF condition and try to transform it
    5194              :    in some way.  When converting a multi-block condition, put the new code
    5195              :    in the first such block and delete the rest.  Return a pointer to this
    5196              :    first block if some transformation was done.  Return NULL otherwise.  */
    5197              : 
    5198              : static basic_block
    5199     39823346 : find_if_header (basic_block test_bb, int pass)
    5200              : {
    5201     39823346 :   ce_if_block ce_info;
    5202     39823346 :   edge then_edge;
    5203     39823346 :   edge else_edge;
    5204              : 
    5205              :   /* The kind of block we're looking for has exactly two successors.  */
    5206     60021567 :   if (EDGE_COUNT (test_bb->succs) != 2)
    5207              :     return NULL;
    5208              : 
    5209     20513955 :   then_edge = EDGE_SUCC (test_bb, 0);
    5210     20513955 :   else_edge = EDGE_SUCC (test_bb, 1);
    5211              : 
    5212     20513955 :   if (df_get_bb_dirty (then_edge->dest))
    5213              :     return NULL;
    5214     20492115 :   if (df_get_bb_dirty (else_edge->dest))
    5215              :     return NULL;
    5216              : 
    5217              :   /* Neither edge should be abnormal.  */
    5218     20455272 :   if ((then_edge->flags & EDGE_COMPLEX)
    5219     18695738 :       || (else_edge->flags & EDGE_COMPLEX))
    5220              :     return NULL;
    5221              : 
    5222              :   /* Nor exit the loop.  */
    5223     18297422 :   if ((then_edge->flags & EDGE_LOOP_EXIT)
    5224     16834216 :       || (else_edge->flags & EDGE_LOOP_EXIT))
    5225              :     return NULL;
    5226              : 
    5227              :   /* The THEN edge is canonically the one that falls through.  */
    5228     14573539 :   if (then_edge->flags & EDGE_FALLTHRU)
    5229              :     ;
    5230      7076140 :   else if (else_edge->flags & EDGE_FALLTHRU)
    5231              :     std::swap (then_edge, else_edge);
    5232              :   else
    5233              :     /* Otherwise this must be a multiway branch of some sort.  */
    5234              :     return NULL;
    5235              : 
    5236     14573198 :   memset (&ce_info, 0, sizeof (ce_info));
    5237     14573198 :   ce_info.test_bb = test_bb;
    5238     14573198 :   ce_info.then_bb = then_edge->dest;
    5239     14573198 :   ce_info.else_bb = else_edge->dest;
    5240     14573198 :   ce_info.pass = pass;
    5241              : 
    5242              : #ifdef IFCVT_MACHDEP_INIT
    5243              :   IFCVT_MACHDEP_INIT (&ce_info);
    5244              : #endif
    5245              : 
    5246     14573198 :   if (!reload_completed
    5247     14573198 :       && noce_find_if_block (test_bb, then_edge, else_edge, pass))
    5248       167649 :     goto success;
    5249              : 
    5250     14405549 :   if (reload_completed
    5251      4687285 :       && targetm.have_conditional_execution ()
    5252     14405549 :       && cond_exec_find_if_block (&ce_info))
    5253            0 :     goto success;
    5254              : 
    5255      9718264 :   if (!reload_completed && targetm.have_trap ()
    5256      9718264 :       && optab_handler (ctrap_optab, word_mode) != CODE_FOR_nothing
    5257     14405549 :       && find_cond_trap (test_bb, then_edge, else_edge))
    5258            0 :     goto success;
    5259              : 
    5260     14405549 :   if (dom_info_state (CDI_POST_DOMINATORS) >= DOM_NO_FAST_QUERY
    5261     14405549 :       && (reload_completed || !targetm.have_conditional_execution ()))
    5262              :     {
    5263     14405549 :       if (find_if_case_1 (test_bb, then_edge, else_edge))
    5264        21455 :         goto success;
    5265     14384094 :       if (find_if_case_2 (test_bb, then_edge, else_edge))
    5266       126630 :         goto success;
    5267              :     }
    5268              : 
    5269              :   return NULL;
    5270              : 
    5271       315734 :  success:
    5272       315734 :   if (dump_file)
    5273           19 :     fprintf (dump_file, "Conversion succeeded on pass %d.\n", pass);
    5274              :   /* Set this so we continue looking.  */
    5275       315734 :   cond_exec_changed_p = true;
    5276       315734 :   return ce_info.test_bb;
    5277              : }
    5278              : 
    5279              : /* Return true if a block has two edges, one of which falls through to the next
    5280              :    block, and the other jumps to a specific block, so that we can tell if the
    5281              :    block is part of an && test or an || test.  Returns either -1 or the number
    5282              :    of non-note, non-jump, non-USE/CLOBBER insns in the block.  */
    5283              : 
    5284              : static int
    5285            0 : block_jumps_and_fallthru (basic_block cur_bb, basic_block target_bb)
    5286              : {
    5287            0 :   edge cur_edge;
    5288            0 :   bool fallthru_p = false;
    5289            0 :   bool jump_p = false;
    5290            0 :   rtx_insn *insn;
    5291            0 :   rtx_insn *end;
    5292            0 :   int n_insns = 0;
    5293            0 :   edge_iterator ei;
    5294              : 
    5295            0 :   if (!cur_bb || !target_bb)
    5296              :     return -1;
    5297              : 
    5298              :   /* If no edges, obviously it doesn't jump or fallthru.  */
    5299            0 :   if (EDGE_COUNT (cur_bb->succs) == 0)
    5300              :     return 0;
    5301              : 
    5302            0 :   FOR_EACH_EDGE (cur_edge, ei, cur_bb->succs)
    5303              :     {
    5304            0 :       if (cur_edge->flags & EDGE_COMPLEX)
    5305              :         /* Anything complex isn't what we want.  */
    5306              :         return -1;
    5307              : 
    5308            0 :       else if (cur_edge->flags & EDGE_FALLTHRU)
    5309              :         fallthru_p = true;
    5310              : 
    5311            0 :       else if (cur_edge->dest == target_bb)
    5312              :         jump_p = true;
    5313              : 
    5314              :       else
    5315              :         return -1;
    5316              :     }
    5317              : 
    5318            0 :   if ((jump_p & fallthru_p) == 0)
    5319              :     return -1;
    5320              : 
    5321              :   /* Don't allow calls in the block, since this is used to group && and ||
    5322              :      together for conditional execution support.  ??? we should support
    5323              :      conditional execution support across calls for IA-64 some day, but
    5324              :      for now it makes the code simpler.  */
    5325            0 :   end = BB_END (cur_bb);
    5326            0 :   insn = BB_HEAD (cur_bb);
    5327              : 
    5328            0 :   while (insn != NULL_RTX)
    5329              :     {
    5330            0 :       if (CALL_P (insn))
    5331              :         return -1;
    5332              : 
    5333            0 :       if (INSN_P (insn)
    5334            0 :           && !JUMP_P (insn)
    5335            0 :           && !DEBUG_INSN_P (insn)
    5336            0 :           && GET_CODE (PATTERN (insn)) != USE
    5337            0 :           && GET_CODE (PATTERN (insn)) != CLOBBER)
    5338            0 :         n_insns++;
    5339              : 
    5340            0 :       if (insn == end)
    5341              :         break;
    5342              : 
    5343            0 :       insn = NEXT_INSN (insn);
    5344              :     }
    5345              : 
    5346              :   return n_insns;
    5347              : }
    5348              : 
    5349              : /* Determine if a given basic block heads a simple IF-THEN or IF-THEN-ELSE
    5350              :    block.  If so, we'll try to convert the insns to not require the branch.
    5351              :    Return TRUE if we were successful at converting the block.  */
    5352              : 
    5353              : static bool
    5354            0 : cond_exec_find_if_block (struct ce_if_block * ce_info)
    5355              : {
    5356            0 :   basic_block test_bb = ce_info->test_bb;
    5357            0 :   basic_block then_bb = ce_info->then_bb;
    5358            0 :   basic_block else_bb = ce_info->else_bb;
    5359            0 :   basic_block join_bb = NULL_BLOCK;
    5360            0 :   edge cur_edge;
    5361            0 :   basic_block next;
    5362            0 :   edge_iterator ei;
    5363              : 
    5364            0 :   ce_info->last_test_bb = test_bb;
    5365              : 
    5366              :   /* We only ever should get here after reload,
    5367              :      and if we have conditional execution.  */
    5368            0 :   gcc_assert (reload_completed && targetm.have_conditional_execution ());
    5369              : 
    5370              :   /* Discover if any fall through predecessors of the current test basic block
    5371              :      were && tests (which jump to the else block) or || tests (which jump to
    5372              :      the then block).  */
    5373            0 :   if (single_pred_p (test_bb)
    5374            0 :       && single_pred_edge (test_bb)->flags == EDGE_FALLTHRU)
    5375              :     {
    5376            0 :       basic_block bb = single_pred (test_bb);
    5377            0 :       basic_block target_bb;
    5378            0 :       int max_insns = MAX_CONDITIONAL_EXECUTE;
    5379            0 :       int n_insns;
    5380              : 
    5381              :       /* Determine if the preceding block is an && or || block.  */
    5382            0 :       if ((n_insns = block_jumps_and_fallthru (bb, else_bb)) >= 0)
    5383              :         {
    5384            0 :           ce_info->and_and_p = true;
    5385            0 :           target_bb = else_bb;
    5386              :         }
    5387            0 :       else if ((n_insns = block_jumps_and_fallthru (bb, then_bb)) >= 0)
    5388              :         {
    5389            0 :           ce_info->and_and_p = false;
    5390            0 :           target_bb = then_bb;
    5391              :         }
    5392              :       else
    5393              :         target_bb = NULL_BLOCK;
    5394              : 
    5395            0 :       if (target_bb && n_insns <= max_insns)
    5396              :         {
    5397            0 :           int total_insns = 0;
    5398            0 :           int blocks = 0;
    5399              : 
    5400            0 :           ce_info->last_test_bb = test_bb;
    5401              : 
    5402              :           /* Found at least one && or || block, look for more.  */
    5403            0 :           do
    5404              :             {
    5405            0 :               ce_info->test_bb = test_bb = bb;
    5406            0 :               total_insns += n_insns;
    5407            0 :               blocks++;
    5408              : 
    5409            0 :               if (!single_pred_p (bb))
    5410              :                 break;
    5411              : 
    5412            0 :               bb = single_pred (bb);
    5413            0 :               n_insns = block_jumps_and_fallthru (bb, target_bb);
    5414              :             }
    5415            0 :           while (n_insns >= 0 && (total_insns + n_insns) <= max_insns);
    5416              : 
    5417            0 :           ce_info->num_multiple_test_blocks = blocks;
    5418            0 :           ce_info->num_multiple_test_insns = total_insns;
    5419              : 
    5420            0 :           if (ce_info->and_and_p)
    5421            0 :             ce_info->num_and_and_blocks = blocks;
    5422              :           else
    5423            0 :             ce_info->num_or_or_blocks = blocks;
    5424              :         }
    5425              :     }
    5426              : 
    5427              :   /* The THEN block of an IF-THEN combo must have exactly one predecessor,
    5428              :      other than any || blocks which jump to the THEN block.  */
    5429            0 :   if ((EDGE_COUNT (then_bb->preds) - ce_info->num_or_or_blocks) != 1)
    5430              :     return false;
    5431              : 
    5432              :   /* The edges of the THEN and ELSE blocks cannot have complex edges.  */
    5433            0 :   FOR_EACH_EDGE (cur_edge, ei, then_bb->preds)
    5434              :     {
    5435            0 :       if (cur_edge->flags & EDGE_COMPLEX)
    5436              :         return false;
    5437              :     }
    5438              : 
    5439            0 :   FOR_EACH_EDGE (cur_edge, ei, else_bb->preds)
    5440              :     {
    5441            0 :       if (cur_edge->flags & EDGE_COMPLEX)
    5442              :         return false;
    5443              :     }
    5444              : 
    5445              :   /* The THEN block of an IF-THEN combo must have zero or one successors.  */
    5446            0 :   if (EDGE_COUNT (then_bb->succs) > 0
    5447            0 :       && (!single_succ_p (then_bb)
    5448            0 :           || (single_succ_edge (then_bb)->flags & EDGE_COMPLEX)
    5449            0 :           || (epilogue_completed
    5450            0 :               && tablejump_p (BB_END (then_bb), NULL, NULL))))
    5451            0 :     return false;
    5452              : 
    5453              :   /* If the THEN block has no successors, conditional execution can still
    5454              :      make a conditional call.  Don't do this unless the ELSE block has
    5455              :      only one incoming edge -- the CFG manipulation is too ugly otherwise.
    5456              :      Check for the last insn of the THEN block being an indirect jump, which
    5457              :      is listed as not having any successors, but confuses the rest of the CE
    5458              :      code processing.  ??? we should fix this in the future.  */
    5459            0 :   if (EDGE_COUNT (then_bb->succs) == 0)
    5460              :     {
    5461            0 :       if (single_pred_p (else_bb) && else_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
    5462              :         {
    5463            0 :           rtx_insn *last_insn = BB_END (then_bb);
    5464              : 
    5465            0 :           while (last_insn
    5466            0 :                  && NOTE_P (last_insn)
    5467            0 :                  && last_insn != BB_HEAD (then_bb))
    5468            0 :             last_insn = PREV_INSN (last_insn);
    5469              : 
    5470            0 :           if (last_insn
    5471            0 :               && JUMP_P (last_insn)
    5472            0 :               && ! simplejump_p (last_insn))
    5473              :             return false;
    5474              : 
    5475              :           join_bb = else_bb;
    5476              :           else_bb = NULL_BLOCK;
    5477              :         }
    5478              :       else
    5479              :         return false;
    5480              :     }
    5481              : 
    5482              :   /* If the THEN block's successor is the other edge out of the TEST block,
    5483              :      then we have an IF-THEN combo without an ELSE.  */
    5484            0 :   else if (single_succ (then_bb) == else_bb)
    5485              :     {
    5486              :       join_bb = else_bb;
    5487              :       else_bb = NULL_BLOCK;
    5488              :     }
    5489              : 
    5490              :   /* If the THEN and ELSE block meet in a subsequent block, and the ELSE
    5491              :      has exactly one predecessor and one successor, and the outgoing edge
    5492              :      is not complex, then we have an IF-THEN-ELSE combo.  */
    5493            0 :   else if (single_succ_p (else_bb)
    5494            0 :            && single_succ (then_bb) == single_succ (else_bb)
    5495            0 :            && single_pred_p (else_bb)
    5496            0 :            && !(single_succ_edge (else_bb)->flags & EDGE_COMPLEX)
    5497            0 :            && !(epilogue_completed
    5498            0 :                 && tablejump_p (BB_END (else_bb), NULL, NULL)))
    5499            0 :     join_bb = single_succ (else_bb);
    5500              : 
    5501              :   /* Otherwise it is not an IF-THEN or IF-THEN-ELSE combination.  */
    5502              :   else
    5503            0 :     return false;
    5504              : 
    5505            0 :   num_possible_if_blocks++;
    5506              : 
    5507            0 :   if (dump_file)
    5508              :     {
    5509            0 :       fprintf (dump_file,
    5510              :                "\nIF-THEN%s block found, pass %d, start block %d "
    5511              :                "[insn %d], then %d [%d]",
    5512              :                (else_bb) ? "-ELSE" : "",
    5513              :                ce_info->pass,
    5514              :                test_bb->index,
    5515            0 :                BB_HEAD (test_bb) ? (int)INSN_UID (BB_HEAD (test_bb)) : -1,
    5516              :                then_bb->index,
    5517            0 :                BB_HEAD (then_bb) ? (int)INSN_UID (BB_HEAD (then_bb)) : -1);
    5518              : 
    5519            0 :       if (else_bb)
    5520            0 :         fprintf (dump_file, ", else %d [%d]",
    5521              :                  else_bb->index,
    5522            0 :                  BB_HEAD (else_bb) ? (int)INSN_UID (BB_HEAD (else_bb)) : -1);
    5523              : 
    5524            0 :       fprintf (dump_file, ", join %d [%d]",
    5525              :                join_bb->index,
    5526            0 :                BB_HEAD (join_bb) ? (int)INSN_UID (BB_HEAD (join_bb)) : -1);
    5527              : 
    5528            0 :       if (ce_info->num_multiple_test_blocks > 0)
    5529            0 :         fprintf (dump_file, ", %d %s block%s last test %d [%d]",
    5530              :                  ce_info->num_multiple_test_blocks,
    5531            0 :                  (ce_info->and_and_p) ? "&&" : "||",
    5532              :                  (ce_info->num_multiple_test_blocks == 1) ? "" : "s",
    5533              :                  ce_info->last_test_bb->index,
    5534            0 :                  ((BB_HEAD (ce_info->last_test_bb))
    5535            0 :                   ? (int)INSN_UID (BB_HEAD (ce_info->last_test_bb))
    5536              :                   : -1));
    5537              : 
    5538            0 :       fputc ('\n', dump_file);
    5539              :     }
    5540              : 
    5541              :   /* Make sure IF, THEN, and ELSE, blocks are adjacent.  Actually, we get the
    5542              :      first condition for free, since we've already asserted that there's a
    5543              :      fallthru edge from IF to THEN.  Likewise for the && and || blocks, since
    5544              :      we checked the FALLTHRU flag, those are already adjacent to the last IF
    5545              :      block.  */
    5546              :   /* ??? As an enhancement, move the ELSE block.  Have to deal with
    5547              :      BLOCK notes, if by no other means than backing out the merge if they
    5548              :      exist.  Sticky enough I don't want to think about it now.  */
    5549            0 :   next = then_bb;
    5550            0 :   if (else_bb && (next = next->next_bb) != else_bb)
    5551              :     return false;
    5552            0 :   if ((next = next->next_bb) != join_bb
    5553            0 :       && join_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
    5554              :     {
    5555            0 :       if (else_bb)
    5556              :         join_bb = NULL;
    5557              :       else
    5558              :         return false;
    5559              :     }
    5560              : 
    5561              :   /* Do the real work.  */
    5562              : 
    5563            0 :   ce_info->else_bb = else_bb;
    5564            0 :   ce_info->join_bb = join_bb;
    5565              : 
    5566              :   /* If we have && and || tests, try to first handle combining the && and ||
    5567              :      tests into the conditional code, and if that fails, go back and handle
    5568              :      it without the && and ||, which at present handles the && case if there
    5569              :      was no ELSE block.  */
    5570            0 :   if (cond_exec_process_if_block (ce_info, true))
    5571              :     return true;
    5572              : 
    5573            0 :   if (ce_info->num_multiple_test_blocks)
    5574              :     {
    5575            0 :       cancel_changes (0);
    5576              : 
    5577            0 :       if (cond_exec_process_if_block (ce_info, false))
    5578              :         return true;
    5579              :     }
    5580              : 
    5581              :   return false;
    5582              : }
    5583              : 
    5584              : /* Convert a branch over a trap, or a branch
    5585              :    to a trap, into a conditional trap.  */
    5586              : 
    5587              : static bool
    5588            0 : find_cond_trap (basic_block test_bb, edge then_edge, edge else_edge)
    5589              : {
    5590            0 :   basic_block then_bb = then_edge->dest;
    5591            0 :   basic_block else_bb = else_edge->dest;
    5592            0 :   basic_block other_bb, trap_bb;
    5593            0 :   rtx_insn *trap, *jump;
    5594            0 :   rtx cond;
    5595            0 :   rtx_insn *cond_earliest;
    5596              : 
    5597              :   /* Locate the block with the trap instruction.  */
    5598              :   /* ??? While we look for no successors, we really ought to allow
    5599              :      EH successors.  Need to fix merge_if_block for that to work.  */
    5600            0 :   if ((trap = block_has_only_trap (then_bb)) != NULL)
    5601              :     trap_bb = then_bb, other_bb = else_bb;
    5602            0 :   else if ((trap = block_has_only_trap (else_bb)) != NULL)
    5603              :     trap_bb = else_bb, other_bb = then_bb;
    5604              :   else
    5605              :     return false;
    5606              : 
    5607            0 :   if (dump_file)
    5608              :     {
    5609            0 :       fprintf (dump_file, "\nTRAP-IF block found, start %d, trap %d\n",
    5610              :                test_bb->index, trap_bb->index);
    5611              :     }
    5612              : 
    5613              :   /* If this is not a standard conditional jump, we can't parse it.  */
    5614            0 :   jump = BB_END (test_bb);
    5615            0 :   cond = noce_get_condition (jump, &cond_earliest, then_bb == trap_bb);
    5616            0 :   if (! cond)
    5617              :     return false;
    5618              : 
    5619              :   /* If the conditional jump is more than just a conditional jump, then
    5620              :      we cannot do if-conversion on this block.  Give up for returnjump_p,
    5621              :      changing a conditional return followed by unconditional trap for
    5622              :      conditional trap followed by unconditional return is likely not
    5623              :      beneficial and harder to handle.  */
    5624            0 :   if (! onlyjump_p (jump) || returnjump_p (jump))
    5625            0 :     return false;
    5626              : 
    5627              :   /* We must be comparing objects whose modes imply the size.  */
    5628            0 :   if (GET_MODE (XEXP (cond, 0)) == BLKmode)
    5629              :     return false;
    5630              : 
    5631              :   /* Attempt to generate the conditional trap.  */
    5632            0 :   rtx_insn *seq = gen_cond_trap (GET_CODE (cond), copy_rtx (XEXP (cond, 0)),
    5633              :                                  copy_rtx (XEXP (cond, 1)),
    5634            0 :                                  TRAP_CODE (PATTERN (trap)));
    5635            0 :   if (seq == NULL)
    5636              :     return false;
    5637              : 
    5638              :   /* If that results in an invalid insn, back out.  */
    5639            0 :   for (rtx_insn *x = seq; x; x = NEXT_INSN (x))
    5640            0 :     if (reload_completed
    5641            0 :         ? !valid_insn_p (x)
    5642            0 :         : recog_memoized (x) < 0)
    5643              :       return false;
    5644              : 
    5645              :   /* Emit the new insns before cond_earliest.  */
    5646            0 :   emit_insn_before_setloc (seq, cond_earliest, INSN_LOCATION (trap));
    5647              : 
    5648              :   /* Delete the trap block if possible.  */
    5649            0 :   remove_edge (trap_bb == then_bb ? then_edge : else_edge);
    5650            0 :   df_set_bb_dirty (test_bb);
    5651            0 :   df_set_bb_dirty (then_bb);
    5652            0 :   df_set_bb_dirty (else_bb);
    5653              : 
    5654            0 :   if (EDGE_COUNT (trap_bb->preds) == 0)
    5655              :     {
    5656            0 :       delete_basic_block (trap_bb);
    5657            0 :       num_true_changes++;
    5658              :     }
    5659              : 
    5660              :   /* Wire together the blocks again.  */
    5661            0 :   if (current_ir_type () == IR_RTL_CFGLAYOUT)
    5662            0 :     single_succ_edge (test_bb)->flags |= EDGE_FALLTHRU;
    5663            0 :   else if (trap_bb == then_bb)
    5664              :     {
    5665            0 :       rtx lab = JUMP_LABEL (jump);
    5666            0 :       rtx_insn *seq = targetm.gen_jump (lab);
    5667            0 :       rtx_jump_insn *newjump = emit_jump_insn_after (seq, jump);
    5668            0 :       LABEL_NUSES (lab) += 1;
    5669            0 :       JUMP_LABEL (newjump) = lab;
    5670            0 :       emit_barrier_after (newjump);
    5671              :     }
    5672            0 :   delete_insn (jump);
    5673              : 
    5674            0 :   if (can_merge_blocks_p (test_bb, other_bb))
    5675              :     {
    5676            0 :       merge_blocks (test_bb, other_bb);
    5677            0 :       num_true_changes++;
    5678              :     }
    5679              : 
    5680            0 :   num_updated_if_blocks++;
    5681            0 :   return true;
    5682              : }
    5683              : 
    5684              : /* Subroutine of find_cond_trap: if BB contains only a trap insn,
    5685              :    return it.  */
    5686              : 
    5687              : static rtx_insn *
    5688            0 : block_has_only_trap (basic_block bb)
    5689              : {
    5690            0 :   rtx_insn *trap;
    5691              : 
    5692              :   /* We're not the exit block.  */
    5693            0 :   if (bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
    5694              :     return NULL;
    5695              : 
    5696              :   /* The block must have no successors.  */
    5697            0 :   if (EDGE_COUNT (bb->succs) > 0)
    5698              :     return NULL;
    5699              : 
    5700              :   /* The only instruction in the THEN block must be the trap.  */
    5701            0 :   trap = first_active_insn (bb);
    5702            0 :   if (! (trap == BB_END (bb)
    5703            0 :          && GET_CODE (PATTERN (trap)) == TRAP_IF
    5704            0 :          && TRAP_CONDITION (PATTERN (trap)) == const_true_rtx))
    5705            0 :     return NULL;
    5706              : 
    5707              :   return trap;
    5708              : }
    5709              : 
    5710              : /* Look for IF-THEN-ELSE cases in which one of THEN or ELSE is
    5711              :    transformable, but not necessarily the other.  There need be no
    5712              :    JOIN block.
    5713              : 
    5714              :    Return TRUE if we were successful at converting the block.
    5715              : 
    5716              :    Cases we'd like to look at:
    5717              : 
    5718              :    (1)
    5719              :         if (test) goto over; // x not live
    5720              :         x = a;
    5721              :         goto label;
    5722              :         over:
    5723              : 
    5724              :    becomes
    5725              : 
    5726              :         x = a;
    5727              :         if (! test) goto label;
    5728              : 
    5729              :    (2)
    5730              :         if (test) goto E; // x not live
    5731              :         x = big();
    5732              :         goto L;
    5733              :         E:
    5734              :         x = b;
    5735              :         goto M;
    5736              : 
    5737              :    becomes
    5738              : 
    5739              :         x = b;
    5740              :         if (test) goto M;
    5741              :         x = big();
    5742              :         goto L;
    5743              : 
    5744              :    (3) // This one's really only interesting for targets that can do
    5745              :        // multiway branching, e.g. IA-64 BBB bundles.  For other targets
    5746              :        // it results in multiple branches on a cache line, which often
    5747              :        // does not sit well with predictors.
    5748              : 
    5749              :         if (test1) goto E; // predicted not taken
    5750              :         x = a;
    5751              :         if (test2) goto F;
    5752              :         ...
    5753              :         E:
    5754              :         x = b;
    5755              :         J:
    5756              : 
    5757              :    becomes
    5758              : 
    5759              :         x = a;
    5760              :         if (test1) goto E;
    5761              :         if (test2) goto F;
    5762              : 
    5763              :    Notes:
    5764              : 
    5765              :    (A) Don't do (2) if the branch is predicted against the block we're
    5766              :    eliminating.  Do it anyway if we can eliminate a branch; this requires
    5767              :    that the sole successor of the eliminated block postdominate the other
    5768              :    side of the if.
    5769              : 
    5770              :    (B) With CE, on (3) we can steal from both sides of the if, creating
    5771              : 
    5772              :         if (test1) x = a;
    5773              :         if (!test1) x = b;
    5774              :         if (test1) goto J;
    5775              :         if (test2) goto F;
    5776              :         ...
    5777              :         J:
    5778              : 
    5779              :    Again, this is most useful if J postdominates.
    5780              : 
    5781              :    (C) CE substitutes for helpful life information.
    5782              : 
    5783              :    (D) These heuristics need a lot of work.  */
    5784              : 
    5785              : /* Tests for case 1 above.  */
    5786              : 
    5787              : static bool
    5788     14405549 : find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
    5789              : {
    5790     14405549 :   basic_block then_bb = then_edge->dest;
    5791     14405549 :   basic_block else_bb = else_edge->dest;
    5792     14405549 :   basic_block new_bb;
    5793     14405549 :   int then_bb_index;
    5794     14405549 :   profile_probability then_prob;
    5795     14405549 :   rtx else_target = NULL_RTX;
    5796              : 
    5797              :   /* If we are partitioning hot/cold basic blocks, we don't want to
    5798              :      mess up unconditional or indirect jumps that cross between hot
    5799              :      and cold sections.
    5800              : 
    5801              :      Basic block partitioning may result in some jumps that appear to
    5802              :      be optimizable (or blocks that appear to be mergeable), but which really
    5803              :      must be left untouched (they are required to make it safely across
    5804              :      partition boundaries).  See  the comments at the top of
    5805              :      bb-reorder.cc:partition_hot_cold_basic_blocks for complete details.  */
    5806              : 
    5807     14405549 :   if ((BB_END (then_bb)
    5808     14405549 :        && JUMP_P (BB_END (then_bb))
    5809      7518631 :        && CROSSING_JUMP_P (BB_END (then_bb)))
    5810     14166675 :       || (JUMP_P (BB_END (test_bb))
    5811     14166675 :           && CROSSING_JUMP_P (BB_END (test_bb)))
    5812     28463014 :       || (BB_END (else_bb)
    5813     14057465 :           && JUMP_P (BB_END (else_bb))
    5814      7123628 :           && CROSSING_JUMP_P (BB_END (else_bb))))
    5815              :     return false;
    5816              : 
    5817              :   /* Verify test_bb ends in a conditional jump with no other side-effects.  */
    5818     14033635 :   if (!onlyjump_p (BB_END (test_bb)))
    5819              :     return false;
    5820              : 
    5821              :   /* THEN has one successor.  */
    5822     20748479 :   if (!single_succ_p (then_bb))
    5823              :     return false;
    5824              : 
    5825              :   /* THEN does not fall through, but is not strange either.  */
    5826      6364385 :   if (single_succ_edge (then_bb)->flags & (EDGE_COMPLEX | EDGE_FALLTHRU))
    5827              :     return false;
    5828              : 
    5829              :   /* THEN has one predecessor.  */
    5830     15517685 :   if (!single_pred_p (then_bb))
    5831              :     return false;
    5832              : 
    5833              :   /* THEN must do something.  */
    5834      1133591 :   if (forwarder_block_p (then_bb))
    5835              :     return false;
    5836              : 
    5837       716640 :   num_possible_if_blocks++;
    5838       716640 :   if (dump_file)
    5839            8 :     fprintf (dump_file,
    5840              :              "\nIF-CASE-1 found, start %d, then %d\n",
    5841              :              test_bb->index, then_bb->index);
    5842              : 
    5843       716640 :   then_prob = then_edge->probability.invert ();
    5844              : 
    5845              :   /* We're speculating from the THEN path, we want to make sure the cost
    5846              :      of speculation is within reason.  */
    5847      1355966 :   if (! cheap_bb_rtx_cost_p (then_bb, then_prob,
    5848      1355966 :         COSTS_N_INSNS (BRANCH_COST (optimize_bb_for_speed_p (then_edge->src),
    5849              :                                     predictable_edge_p (then_edge)))))
    5850              :     return false;
    5851              : 
    5852       143222 :   if (else_bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
    5853              :     {
    5854            0 :       rtx_insn *jump = BB_END (else_edge->src);
    5855            0 :       gcc_assert (JUMP_P (jump));
    5856            0 :       else_target = JUMP_LABEL (jump);
    5857              :     }
    5858              : 
    5859              :   /* Registers set are dead, or are predicable.  */
    5860       143222 :   if (! dead_or_predicable (test_bb, then_bb, else_bb,
    5861              :                             single_succ_edge (then_bb), true))
    5862              :     return false;
    5863              : 
    5864              :   /* Conversion went ok, including moving the insns and fixing up the
    5865              :      jump.  Adjust the CFG to match.  */
    5866              : 
    5867              :   /* We can avoid creating a new basic block if then_bb is immediately
    5868              :      followed by else_bb, i.e. deleting then_bb allows test_bb to fall
    5869              :      through to else_bb.  */
    5870              : 
    5871        21455 :   if (then_bb->next_bb == else_bb
    5872        10355 :       && then_bb->prev_bb == test_bb
    5873        10355 :       && else_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
    5874              :     {
    5875        10355 :       redirect_edge_succ (FALLTHRU_EDGE (test_bb), else_bb);
    5876        10355 :       new_bb = 0;
    5877              :     }
    5878        11100 :   else if (else_bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
    5879            0 :     new_bb = force_nonfallthru_and_redirect (FALLTHRU_EDGE (test_bb),
    5880              :                                              else_bb, else_target);
    5881              :   else
    5882        11100 :     new_bb = redirect_edge_and_branch_force (FALLTHRU_EDGE (test_bb),
    5883              :                                              else_bb);
    5884              : 
    5885        21455 :   df_set_bb_dirty (test_bb);
    5886        21455 :   df_set_bb_dirty (else_bb);
    5887              : 
    5888        21455 :   then_bb_index = then_bb->index;
    5889        21455 :   delete_basic_block (then_bb);
    5890              : 
    5891              :   /* Make rest of code believe that the newly created block is the THEN_BB
    5892              :      block we removed.  */
    5893        21455 :   if (new_bb)
    5894              :     {
    5895        11100 :       df_bb_replace (then_bb_index, new_bb);
    5896              :       /* This should have been done above via force_nonfallthru_and_redirect
    5897              :          (possibly called from redirect_edge_and_branch_force).  */
    5898        11100 :       gcc_checking_assert (BB_PARTITION (new_bb) == BB_PARTITION (test_bb));
    5899              :     }
    5900              : 
    5901        21455 :   num_true_changes++;
    5902        21455 :   num_updated_if_blocks++;
    5903        21455 :   return true;
    5904              : }
    5905              : 
    5906              : /* Test for case 2 above.  */
    5907              : 
    5908              : static bool
    5909     14384094 : find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge)
    5910              : {
    5911     14384094 :   basic_block then_bb = then_edge->dest;
    5912     14384094 :   basic_block else_bb = else_edge->dest;
    5913     14384094 :   edge else_succ;
    5914     14384094 :   profile_probability then_prob, else_prob;
    5915              : 
    5916              :   /* We do not want to speculate (empty) loop latches.  */
    5917     14384094 :   if (current_loops
    5918      5592676 :       && else_bb->loop_father->latch == else_bb)
    5919              :     return false;
    5920              : 
    5921              :   /* If we are partitioning hot/cold basic blocks, we don't want to
    5922              :      mess up unconditional or indirect jumps that cross between hot
    5923              :      and cold sections.
    5924              : 
    5925              :      Basic block partitioning may result in some jumps that appear to
    5926              :      be optimizable (or blocks that appear to be mergeable), but which really
    5927              :      must be left untouched (they are required to make it safely across
    5928              :      partition boundaries).  See  the comments at the top of
    5929              :      bb-reorder.cc:partition_hot_cold_basic_blocks for complete details.  */
    5930              : 
    5931     14230012 :   if ((BB_END (then_bb)
    5932     14230012 :        && JUMP_P (BB_END (then_bb))
    5933      7421881 :        && CROSSING_JUMP_P (BB_END (then_bb)))
    5934     13991138 :       || (JUMP_P (BB_END (test_bb))
    5935     13991138 :           && CROSSING_JUMP_P (BB_END (test_bb)))
    5936     28111940 :       || (BB_END (else_bb)
    5937     13881928 :           && JUMP_P (BB_END (else_bb))
    5938      6980206 :           && CROSSING_JUMP_P (BB_END (else_bb))))
    5939              :     return false;
    5940              : 
    5941              :   /* Verify test_bb ends in a conditional jump with no other side-effects.  */
    5942     13858098 :   if (!onlyjump_p (BB_END (test_bb)))
    5943              :     return false;
    5944              : 
    5945              :   /* ELSE has one successor.  */
    5946     20090380 :   if (!single_succ_p (else_bb))
    5947              :     return false;
    5948              :   else
    5949      5832916 :     else_succ = single_succ_edge (else_bb);
    5950              : 
    5951              :   /* ELSE outgoing edge is not complex.  */
    5952      5832916 :   if (else_succ->flags & EDGE_COMPLEX)
    5953              :     return false;
    5954              : 
    5955              :   /* ELSE has one predecessor.  */
    5956     17225480 :   if (!single_pred_p (else_bb))
    5957              :     return false;
    5958              : 
    5959              :   /* THEN is not EXIT.  */
    5960      2968016 :   if (then_bb->index < NUM_FIXED_BLOCKS)
    5961              :     return false;
    5962              : 
    5963      2968016 :   else_prob = else_edge->probability;
    5964      2968016 :   then_prob = else_prob.invert ();
    5965              : 
    5966              :   /* ELSE is predicted or SUCC(ELSE) postdominates THEN.  */
    5967      2968016 :   if (else_prob > then_prob)
    5968              :     ;
    5969      1992396 :   else if (else_succ->dest->index < NUM_FIXED_BLOCKS
    5970      1992396 :            || dominated_by_p (CDI_POST_DOMINATORS, then_bb,
    5971              :                               else_succ->dest))
    5972              :     ;
    5973              :   else
    5974              :     return false;
    5975              : 
    5976      2340398 :   num_possible_if_blocks++;
    5977      2340398 :   if (dump_file)
    5978           44 :     fprintf (dump_file,
    5979              :              "\nIF-CASE-2 found, start %d, else %d\n",
    5980              :              test_bb->index, else_bb->index);
    5981              : 
    5982              :   /* We're speculating from the ELSE path, we want to make sure the cost
    5983              :      of speculation is within reason.  */
    5984      4509881 :   if (! cheap_bb_rtx_cost_p (else_bb, else_prob,
    5985      4509881 :         COSTS_N_INSNS (BRANCH_COST (optimize_bb_for_speed_p (else_edge->src),
    5986              :                                     predictable_edge_p (else_edge)))))
    5987              :     return false;
    5988              : 
    5989              :   /* Registers set are dead, or are predicable.  */
    5990       458281 :   if (! dead_or_predicable (test_bb, else_bb, then_bb, else_succ, false))
    5991              :     return false;
    5992              : 
    5993              :   /* Conversion went ok, including moving the insns and fixing up the
    5994              :      jump.  Adjust the CFG to match.  */
    5995              : 
    5996       126630 :   df_set_bb_dirty (test_bb);
    5997       126630 :   df_set_bb_dirty (then_bb);
    5998       126630 :   delete_basic_block (else_bb);
    5999              : 
    6000       126630 :   num_true_changes++;
    6001       126630 :   num_updated_if_blocks++;
    6002              : 
    6003              :   /* ??? We may now fallthru from one of THEN's successors into a join
    6004              :      block.  Rerun cleanup_cfg?  Examine things manually?  Wait?  */
    6005              : 
    6006       126630 :   return true;
    6007              : }
    6008              : 
    6009              : /* Used by the code above to perform the actual rtl transformations.
    6010              :    Return TRUE if successful.
    6011              : 
    6012              :    TEST_BB is the block containing the conditional branch.  MERGE_BB
    6013              :    is the block containing the code to manipulate.  DEST_EDGE is an
    6014              :    edge representing a jump to the join block; after the conversion,
    6015              :    TEST_BB should be branching to its destination.
    6016              :    REVERSEP is true if the sense of the branch should be reversed.  */
    6017              : 
    6018              : static bool
    6019       601503 : dead_or_predicable (basic_block test_bb, basic_block merge_bb,
    6020              :                     basic_block other_bb, edge dest_edge, bool reversep)
    6021              : {
    6022       601503 :   basic_block new_dest = dest_edge->dest;
    6023       601503 :   rtx_insn *head, *end, *jump;
    6024       601503 :   rtx_insn *earliest = NULL;
    6025       601503 :   rtx old_dest;
    6026       601503 :   bitmap merge_set = NULL;
    6027              :   /* Number of pending changes.  */
    6028       601503 :   int n_validated_changes = 0;
    6029       601503 :   rtx new_dest_label = NULL_RTX;
    6030              : 
    6031       601503 :   jump = BB_END (test_bb);
    6032              : 
    6033              :   /* Find the extent of the real code in the merge block.  */
    6034       601503 :   head = BB_HEAD (merge_bb);
    6035       601503 :   end = BB_END (merge_bb);
    6036              : 
    6037       779849 :   while (DEBUG_INSN_P (end) && end != head)
    6038       178346 :     end = PREV_INSN (end);
    6039              : 
    6040              :   /* If merge_bb ends with a tablejump, predicating/moving insn's
    6041              :      into test_bb and then deleting merge_bb will result in the jumptable
    6042              :      that follows merge_bb being removed along with merge_bb and then we
    6043              :      get an unresolved reference to the jumptable.  */
    6044       601503 :   if (tablejump_p (end, NULL, NULL))
    6045              :     return false;
    6046              : 
    6047       601503 :   if (LABEL_P (head))
    6048       458342 :     head = NEXT_INSN (head);
    6049       601503 :   while (DEBUG_INSN_P (head) && head != end)
    6050            0 :     head = NEXT_INSN (head);
    6051       601503 :   if (NOTE_P (head))
    6052              :     {
    6053       601503 :       if (head == end)
    6054              :         {
    6055       104340 :           head = end = NULL;
    6056       104340 :           goto no_body;
    6057              :         }
    6058       497163 :       head = NEXT_INSN (head);
    6059      1366044 :       while (DEBUG_INSN_P (head) && head != end)
    6060       371718 :         head = NEXT_INSN (head);
    6061              :     }
    6062              : 
    6063       497163 :   if (JUMP_P (end))
    6064              :     {
    6065       205274 :       if (!onlyjump_p (end))
    6066              :         return false;
    6067       164214 :       if (head == end)
    6068              :         {
    6069            6 :           head = end = NULL;
    6070            6 :           goto no_body;
    6071              :         }
    6072       164208 :       end = PREV_INSN (end);
    6073       434278 :       while (DEBUG_INSN_P (end) && end != head)
    6074       105862 :         end = PREV_INSN (end);
    6075              :     }
    6076              : 
    6077              :   /* Don't move frame-related insn across the conditional branch.  This
    6078              :      can lead to one of the paths of the branch having wrong unwind info.  */
    6079       456097 :   if (epilogue_completed)
    6080              :     {
    6081              :       rtx_insn *insn = head;
    6082        82081 :       while (1)
    6083              :         {
    6084       287619 :           if (INSN_P (insn) && RTX_FRAME_RELATED_P (insn))
    6085              :             return false;
    6086       281004 :           if (insn == end)
    6087              :             break;
    6088        82081 :           insn = NEXT_INSN (insn);
    6089        82081 :         }
    6090              :     }
    6091              : 
    6092              :   /* Disable handling dead code by conditional execution if the machine needs
    6093              :      to do anything funny with the tests, etc.  */
    6094              : #ifndef IFCVT_MODIFY_TESTS
    6095       449482 :   if (targetm.have_conditional_execution ())
    6096              :     {
    6097              :       /* In the conditional execution case, we have things easy.  We know
    6098              :          the condition is reversible.  We don't have to check life info
    6099              :          because we're going to conditionally execute the code anyway.
    6100              :          All that's left is making sure the insns involved can actually
    6101              :          be predicated.  */
    6102              : 
    6103            0 :       rtx cond;
    6104              : 
    6105              :       /* If the conditional jump is more than just a conditional jump,
    6106              :          then we cannot do conditional execution conversion on this block.  */
    6107            0 :       if (!onlyjump_p (jump))
    6108            0 :         goto nce;
    6109              : 
    6110            0 :       cond = cond_exec_get_condition (jump);
    6111            0 :       if (! cond)
    6112            0 :         goto nce;
    6113              : 
    6114            0 :       rtx note = find_reg_note (jump, REG_BR_PROB, NULL_RTX);
    6115            0 :       profile_probability prob_val
    6116            0 :           = (note ? profile_probability::from_reg_br_prob_note (XINT (note, 0))
    6117            0 :              : profile_probability::uninitialized ());
    6118              : 
    6119            0 :       if (reversep)
    6120              :         {
    6121            0 :           enum rtx_code rev = reversed_comparison_code (cond, jump);
    6122            0 :           if (rev == UNKNOWN)
    6123            0 :             return false;
    6124            0 :           cond = gen_rtx_fmt_ee (rev, GET_MODE (cond), XEXP (cond, 0),
    6125              :                                  XEXP (cond, 1));
    6126            0 :           prob_val = prob_val.invert ();
    6127              :         }
    6128              : 
    6129            0 :       if (cond_exec_process_insns (NULL, head, end, cond, prob_val, false)
    6130            0 :           && verify_changes (0))
    6131            0 :         n_validated_changes = num_validated_changes ();
    6132              :       else
    6133            0 :         cancel_changes (0);
    6134              : 
    6135            0 :       earliest = jump;
    6136              :     }
    6137       449482 :  nce:
    6138              : #endif
    6139              : 
    6140              :   /* If we allocated new pseudos (e.g. in the conditional move
    6141              :      expander called from noce_emit_cmove), we must resize the
    6142              :      array first.  */
    6143       449482 :   if (max_regno < max_reg_num ())
    6144        81236 :     max_regno = max_reg_num ();
    6145              : 
    6146              :   /* Try the NCE path if the CE path did not result in any changes.  */
    6147       449482 :   if (n_validated_changes == 0)
    6148              :     {
    6149       449482 :       rtx cond;
    6150       449482 :       rtx_insn *insn;
    6151       449482 :       regset live;
    6152       449482 :       bool success;
    6153              : 
    6154              :       /* In the non-conditional execution case, we have to verify that there
    6155              :          are no trapping operations, no calls, no references to memory, and
    6156              :          that any registers modified are dead at the branch site.  */
    6157              : 
    6158       449482 :       if (!any_condjump_p (jump))
    6159              :         return false;
    6160              : 
    6161              :       /* Find the extent of the conditional.  */
    6162       449482 :       cond = noce_get_condition (jump, &earliest, false);
    6163       449482 :       if (!cond)
    6164              :         return false;
    6165              : 
    6166       448674 :       live = BITMAP_ALLOC (&reg_obstack);
    6167       448674 :       simulate_backwards_to_point (merge_bb, live, end);
    6168       448674 :       success = can_move_insns_across (head, end, earliest, jump,
    6169              :                                        merge_bb, live,
    6170              :                                        df_get_live_in (other_bb), NULL);
    6171       448674 :       BITMAP_FREE (live);
    6172       448674 :       if (!success)
    6173              :         return false;
    6174              : 
    6175              :       /* Collect the set of registers set in MERGE_BB.  */
    6176       145131 :       merge_set = BITMAP_ALLOC (&reg_obstack);
    6177              : 
    6178       696277 :       FOR_BB_INSNS (merge_bb, insn)
    6179       551146 :         if (NONDEBUG_INSN_P (insn))
    6180       189738 :           df_simulate_find_defs (insn, merge_set);
    6181              : 
    6182              :       /* If shrink-wrapping, disable this optimization when test_bb is
    6183              :          the first basic block and merge_bb exits.  The idea is to not
    6184              :          move code setting up a return register as that may clobber a
    6185              :          register used to pass function parameters, which then must be
    6186              :          saved in caller-saved regs.  A caller-saved reg requires the
    6187              :          prologue, killing a shrink-wrap opportunity.  */
    6188       145130 :       if ((SHRINK_WRAPPING_ENABLED && !epilogue_completed)
    6189       114799 :           && ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb == test_bb
    6190        18854 :           && single_succ_p (new_dest)
    6191        13940 :           && single_succ (new_dest) == EXIT_BLOCK_PTR_FOR_FN (cfun)
    6192       158063 :           && bitmap_intersect_p (df_get_live_in (new_dest), merge_set))
    6193              :         {
    6194        12932 :           regset return_regs;
    6195        12932 :           unsigned int i;
    6196              : 
    6197        12932 :           return_regs = BITMAP_ALLOC (&reg_obstack);
    6198              : 
    6199              :           /* Start off with the intersection of regs used to pass
    6200              :              params and regs used to return values.  */
    6201      1215608 :           for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
    6202      1189744 :             if (FUNCTION_ARG_REGNO_P (i)
    6203      1189744 :                 && targetm.calls.function_value_regno_p (i))
    6204        50558 :               bitmap_set_bit (return_regs, INCOMING_REGNO (i));
    6205              : 
    6206        12932 :           bitmap_and_into (return_regs,
    6207        12932 :                            df_get_live_out (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
    6208        12932 :           bitmap_and_into (return_regs,
    6209        12932 :                            df_get_live_in (EXIT_BLOCK_PTR_FOR_FN (cfun)));
    6210        12932 :           if (!bitmap_empty_p (return_regs))
    6211              :             {
    6212         4774 :               FOR_BB_INSNS_REVERSE (new_dest, insn)
    6213         4229 :                 if (NONDEBUG_INSN_P (insn))
    6214              :                   {
    6215         2151 :                     df_ref def;
    6216              : 
    6217              :                     /* If this insn sets any reg in return_regs, add all
    6218              :                        reg uses to the set of regs we're interested in.  */
    6219         2728 :                     FOR_EACH_INSN_DEF (def, insn)
    6220         1672 :                       if (bitmap_bit_p (return_regs, DF_REF_REGNO (def)))
    6221              :                         {
    6222         1095 :                           df_simulate_uses (insn, return_regs);
    6223         1095 :                           break;
    6224              :                         }
    6225              :                   }
    6226          545 :               if (bitmap_intersect_p (merge_set, return_regs))
    6227              :                 {
    6228          527 :                   BITMAP_FREE (return_regs);
    6229          527 :                   BITMAP_FREE (merge_set);
    6230          527 :                   return false;
    6231              :                 }
    6232              :             }
    6233        12405 :           BITMAP_FREE (return_regs);
    6234              :         }
    6235              :     }
    6236              : 
    6237       248950 :  no_body:
    6238              :   /* We don't want to use normal invert_jump or redirect_jump because
    6239              :      we don't want to delete_insn called.  Also, we want to do our own
    6240              :      change group management.  */
    6241              : 
    6242       248950 :   old_dest = JUMP_LABEL (jump);
    6243       248950 :   if (other_bb != new_dest)
    6244              :     {
    6245       248931 :       if (!any_condjump_p (jump))
    6246            0 :         goto cancel;
    6247              : 
    6248       248931 :       if (JUMP_P (BB_END (dest_edge->src)))
    6249        22424 :         new_dest_label = JUMP_LABEL (BB_END (dest_edge->src));
    6250       226507 :       else if (new_dest == EXIT_BLOCK_PTR_FOR_FN (cfun))
    6251       100865 :         new_dest_label = ret_rtx;
    6252              :       else
    6253       125642 :         new_dest_label = block_label (new_dest);
    6254              : 
    6255       248931 :       rtx_jump_insn *jump_insn = as_a <rtx_jump_insn *> (jump);
    6256       248931 :       if (reversep
    6257       248931 :           ? ! invert_jump_1 (jump_insn, new_dest_label)
    6258       227476 :           : ! redirect_jump_1 (jump_insn, new_dest_label))
    6259            0 :         goto cancel;
    6260              :     }
    6261              : 
    6262       248950 :   if (verify_changes (n_validated_changes))
    6263       148085 :     confirm_change_group ();
    6264              :   else
    6265       100865 :     goto cancel;
    6266              : 
    6267       148085 :   if (other_bb != new_dest)
    6268              :     {
    6269       148066 :       redirect_jump_2 (as_a <rtx_jump_insn *> (jump), old_dest, new_dest_label,
    6270              :                        0, reversep);
    6271              : 
    6272       148066 :       redirect_edge_succ (BRANCH_EDGE (test_bb), new_dest);
    6273       148066 :       if (reversep)
    6274              :         {
    6275        21455 :           std::swap (BRANCH_EDGE (test_bb)->probability,
    6276        21455 :                      FALLTHRU_EDGE (test_bb)->probability);
    6277        21455 :           update_br_prob_note (test_bb);
    6278              :         }
    6279              :     }
    6280              : 
    6281              :   /* Move the insns out of MERGE_BB to before the branch.  */
    6282       148085 :   if (head != NULL)
    6283              :     {
    6284       144604 :       rtx_insn *insn;
    6285              : 
    6286       144604 :       if (end == BB_END (merge_bb))
    6287       111056 :         BB_END (merge_bb) = PREV_INSN (head);
    6288              : 
    6289              :       /* PR 21767: when moving insns above a conditional branch, the REG_EQUAL
    6290              :          notes being moved might become invalid.  */
    6291              :       insn = head;
    6292       173732 :       do
    6293              :         {
    6294       173732 :           rtx note;
    6295              : 
    6296       173732 :           if (! INSN_P (insn))
    6297         3203 :             continue;
    6298       170529 :           note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
    6299       170529 :           if (! note)
    6300       159407 :             continue;
    6301        11122 :           remove_note (insn, note);
    6302       202860 :         } while (insn != end && (insn = NEXT_INSN (insn)));
    6303              : 
    6304              :       /* PR46315: when moving insns above a conditional branch, the REG_EQUAL
    6305              :          notes referring to the registers being set might become invalid.  */
    6306       144604 :       if (merge_set)
    6307              :         {
    6308       144604 :           unsigned i;
    6309       144604 :           bitmap_iterator bi;
    6310              : 
    6311       326330 :           EXECUTE_IF_SET_IN_BITMAP (merge_set, 0, i, bi)
    6312       181726 :             remove_reg_equal_equiv_notes_for_regno (i);
    6313              : 
    6314       144604 :           BITMAP_FREE (merge_set);
    6315              :         }
    6316              : 
    6317       144604 :       reorder_insns (head, end, PREV_INSN (earliest));
    6318              :     }
    6319              : 
    6320              :   /* Remove the jump and edge if we can.  */
    6321       148085 :   if (other_bb == new_dest)
    6322              :     {
    6323           19 :       delete_insn (jump);
    6324           19 :       remove_edge (BRANCH_EDGE (test_bb));
    6325              :       /* ??? Can't merge blocks here, as then_bb is still in use.
    6326              :          At minimum, the merge will get done just before bb-reorder.  */
    6327              :     }
    6328              : 
    6329              :   return true;
    6330              : 
    6331       100865 :  cancel:
    6332       100865 :   cancel_changes (0);
    6333              : 
    6334       100865 :   if (merge_set)
    6335            0 :     BITMAP_FREE (merge_set);
    6336              : 
    6337              :   return false;
    6338              : }
    6339              : 
    6340              : /* Main entry point for all if-conversion.  AFTER_COMBINE is true if
    6341              :    we are after combine pass.  */
    6342              : 
    6343              : static void
    6344      3163909 : if_convert (bool after_combine)
    6345              : {
    6346      3163909 :   basic_block bb;
    6347      3163909 :   int pass;
    6348              : 
    6349      3163909 :   if (optimize == 1)
    6350              :     {
    6351       234541 :       df_live_add_problem ();
    6352       234541 :       df_live_set_all_dirty ();
    6353              :     }
    6354              : 
    6355              :   /* Record whether we are after combine pass.  */
    6356      3163909 :   ifcvt_after_combine = after_combine;
    6357      3163909 :   have_cbranchcc4 = (direct_optab_handler (cbranch_optab, CCmode)
    6358      3163909 :                      != CODE_FOR_nothing);
    6359      3163909 :   num_possible_if_blocks = 0;
    6360      3163909 :   num_updated_if_blocks = 0;
    6361      3163909 :   num_true_changes = 0;
    6362              : 
    6363      3163909 :   loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
    6364      3163909 :   mark_loop_exit_edges ();
    6365      3163909 :   loop_optimizer_finalize ();
    6366      3163909 :   free_dominance_info (CDI_DOMINATORS);
    6367              : 
    6368              :   /* Compute postdominators.  */
    6369      3163909 :   calculate_dominance_info (CDI_POST_DOMINATORS);
    6370              : 
    6371      3163909 :   df_set_flags (DF_LR_RUN_DCE);
    6372              : 
    6373              :   /* Go through each of the basic blocks looking for things to convert.  If we
    6374              :      have conditional execution, we make multiple passes to allow us to handle
    6375              :      IF-THEN{-ELSE} blocks within other IF-THEN{-ELSE} blocks.  */
    6376      3163909 :   pass = 0;
    6377      3328156 :   do
    6378              :     {
    6379      3328156 :       df_analyze ();
    6380              :       /* Only need to do dce on the first pass.  */
    6381      3328156 :       df_clear_flags (DF_LR_RUN_DCE);
    6382      3328156 :       cond_exec_changed_p = false;
    6383      3328156 :       pass++;
    6384              : 
    6385              : #ifdef IFCVT_MULTIPLE_DUMPS
    6386      3328156 :       if (dump_file && pass > 1)
    6387           19 :         fprintf (dump_file, "\n\n========== Pass %d ==========\n", pass);
    6388              : #endif
    6389              : 
    6390     43315886 :       FOR_EACH_BB_FN (bb, cfun)
    6391              :         {
    6392              :           basic_block new_bb;
    6393     40303464 :           while (!df_get_bb_dirty (bb)
    6394     79811076 :                  && (new_bb = find_if_header (bb, pass)) != NULL)
    6395              :             bb = new_bb;
    6396              :         }
    6397              : 
    6398              : #ifdef IFCVT_MULTIPLE_DUMPS
    6399      3328156 :       if (dump_file && cond_exec_changed_p)
    6400           19 :         print_rtl_with_bb (dump_file, get_insns (), dump_flags);
    6401              : #endif
    6402              :     }
    6403              :   while (cond_exec_changed_p);
    6404              : 
    6405              : #ifdef IFCVT_MULTIPLE_DUMPS
    6406      3163909 :   if (dump_file)
    6407           85 :     fprintf (dump_file, "\n\n========== no more changes\n");
    6408              : #endif
    6409              : 
    6410      3163909 :   free_dominance_info (CDI_POST_DOMINATORS);
    6411              : 
    6412      3163909 :   if (dump_file)
    6413           85 :     fflush (dump_file);
    6414              : 
    6415      3163909 :   clear_aux_for_blocks ();
    6416              : 
    6417              :   /* If we allocated new pseudos, we must resize the array for sched1.  */
    6418      3163909 :   if (max_regno < max_reg_num ())
    6419       638675 :     max_regno = max_reg_num ();
    6420              : 
    6421              :   /* Write the final stats.  */
    6422      3163909 :   if (dump_file && num_possible_if_blocks > 0)
    6423              :     {
    6424           59 :       fprintf (dump_file,
    6425              :                "\n%d possible IF blocks searched.\n",
    6426              :                num_possible_if_blocks);
    6427           59 :       fprintf (dump_file,
    6428              :                "%d IF blocks converted.\n",
    6429              :                num_updated_if_blocks);
    6430           59 :       fprintf (dump_file,
    6431              :                "%d true changes made.\n\n\n",
    6432              :                num_true_changes);
    6433              :     }
    6434              : 
    6435      3163909 :   if (optimize == 1)
    6436       234541 :     df_remove_problem (df_live);
    6437              : 
    6438              :   /* Some non-cold blocks may now be only reachable from cold blocks.
    6439              :      Fix that up.  */
    6440      3163909 :   fixup_partitions ();
    6441              : 
    6442      3163909 :   checking_verify_flow_info ();
    6443      3163909 : }
    6444              : 
    6445              : /* If-conversion and CFG cleanup.  */
    6446              : static void
    6447      1057059 : rest_of_handle_if_conversion (void)
    6448              : {
    6449      1057059 :   int flags = 0;
    6450              : 
    6451      1057059 :   if (flag_if_conversion)
    6452              :     {
    6453      1054632 :       if (dump_file)
    6454              :         {
    6455           33 :           dump_reg_info (dump_file);
    6456           33 :           dump_flow_info (dump_file, dump_flags);
    6457              :         }
    6458      1054632 :       cleanup_cfg (CLEANUP_EXPENSIVE);
    6459      1054632 :       if_convert (false);
    6460      1054632 :       if (num_updated_if_blocks)
    6461              :         /* Get rid of any dead CC-related instructions.  */
    6462      1057059 :         flags |= CLEANUP_FORCE_FAST_DCE;
    6463              :     }
    6464              : 
    6465      1057059 :   cleanup_cfg (flags);
    6466      1057059 : }
    6467              : 
    6468              : namespace {
    6469              : 
    6470              : const pass_data pass_data_rtl_ifcvt =
    6471              : {
    6472              :   RTL_PASS, /* type */
    6473              :   "ce1", /* name */
    6474              :   OPTGROUP_NONE, /* optinfo_flags */
    6475              :   TV_IFCVT, /* tv_id */
    6476              :   0, /* properties_required */
    6477              :   0, /* properties_provided */
    6478              :   0, /* properties_destroyed */
    6479              :   0, /* todo_flags_start */
    6480              :   TODO_df_finish, /* todo_flags_finish */
    6481              : };
    6482              : 
    6483              : class pass_rtl_ifcvt : public rtl_opt_pass
    6484              : {
    6485              : public:
    6486       292371 :   pass_rtl_ifcvt (gcc::context *ctxt)
    6487       584742 :     : rtl_opt_pass (pass_data_rtl_ifcvt, ctxt)
    6488              :   {}
    6489              : 
    6490              :   /* opt_pass methods: */
    6491      1504958 :   bool gate (function *) final override
    6492              :     {
    6493      1504958 :       return (optimize > 0) && dbg_cnt (if_conversion);
    6494              :     }
    6495              : 
    6496      1057059 :   unsigned int execute (function *) final override
    6497              :     {
    6498      1057059 :       rest_of_handle_if_conversion ();
    6499      1057059 :       return 0;
    6500              :     }
    6501              : 
    6502              : }; // class pass_rtl_ifcvt
    6503              : 
    6504              : } // anon namespace
    6505              : 
    6506              : rtl_opt_pass *
    6507       292371 : make_pass_rtl_ifcvt (gcc::context *ctxt)
    6508              : {
    6509       292371 :   return new pass_rtl_ifcvt (ctxt);
    6510              : }
    6511              : 
    6512              : 
    6513              : /* Rerun if-conversion, as combine may have simplified things enough
    6514              :    to now meet sequence length restrictions.  */
    6515              : 
    6516              : namespace {
    6517              : 
    6518              : const pass_data pass_data_if_after_combine =
    6519              : {
    6520              :   RTL_PASS, /* type */
    6521              :   "ce2", /* name */
    6522              :   OPTGROUP_NONE, /* optinfo_flags */
    6523              :   TV_IFCVT, /* tv_id */
    6524              :   0, /* properties_required */
    6525              :   0, /* properties_provided */
    6526              :   0, /* properties_destroyed */
    6527              :   0, /* todo_flags_start */
    6528              :   TODO_df_finish, /* todo_flags_finish */
    6529              : };
    6530              : 
    6531              : class pass_if_after_combine : public rtl_opt_pass
    6532              : {
    6533              : public:
    6534       292371 :   pass_if_after_combine (gcc::context *ctxt)
    6535       584742 :     : rtl_opt_pass (pass_data_if_after_combine, ctxt)
    6536              :   {}
    6537              : 
    6538              :   /* opt_pass methods: */
    6539      1504958 :   bool gate (function *) final override
    6540              :     {
    6541      1057060 :       return optimize > 0 && flag_if_conversion
    6542      2559591 :         && dbg_cnt (if_after_combine);
    6543              :     }
    6544              : 
    6545      1054632 :   unsigned int execute (function *) final override
    6546              :     {
    6547      1054632 :       if_convert (true);
    6548      1054632 :       return 0;
    6549              :     }
    6550              : 
    6551              : }; // class pass_if_after_combine
    6552              : 
    6553              : } // anon namespace
    6554              : 
    6555              : rtl_opt_pass *
    6556       292371 : make_pass_if_after_combine (gcc::context *ctxt)
    6557              : {
    6558       292371 :   return new pass_if_after_combine (ctxt);
    6559              : }
    6560              : 
    6561              : 
    6562              : namespace {
    6563              : 
    6564              : const pass_data pass_data_if_after_reload =
    6565              : {
    6566              :   RTL_PASS, /* type */
    6567              :   "ce3", /* name */
    6568              :   OPTGROUP_NONE, /* optinfo_flags */
    6569              :   TV_IFCVT2, /* tv_id */
    6570              :   0, /* properties_required */
    6571              :   0, /* properties_provided */
    6572              :   0, /* properties_destroyed */
    6573              :   0, /* todo_flags_start */
    6574              :   TODO_df_finish, /* todo_flags_finish */
    6575              : };
    6576              : 
    6577              : class pass_if_after_reload : public rtl_opt_pass
    6578              : {
    6579              : public:
    6580       292371 :   pass_if_after_reload (gcc::context *ctxt)
    6581       584742 :     : rtl_opt_pass (pass_data_if_after_reload, ctxt)
    6582              :   {}
    6583              : 
    6584              :   /* opt_pass methods: */
    6585      1504958 :   bool gate (function *) final override
    6586              :     {
    6587      1057060 :       return optimize > 0 && flag_if_conversion2
    6588      2559604 :         && dbg_cnt (if_after_reload);
    6589              :     }
    6590              : 
    6591      1054645 :   unsigned int execute (function *) final override
    6592              :     {
    6593      1054645 :       if_convert (true);
    6594      1054645 :       return 0;
    6595              :     }
    6596              : 
    6597              : }; // class pass_if_after_reload
    6598              : 
    6599              : } // anon namespace
    6600              : 
    6601              : rtl_opt_pass *
    6602       292371 : make_pass_if_after_reload (gcc::context *ctxt)
    6603              : {
    6604       292371 :   return new pass_if_after_reload (ctxt);
    6605              : }
        

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.