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