tree-ssa-phiopt.c revision 169689
1207141Sjeff/* Optimization of PHI nodes by converting them into straightline code.
2207141Sjeff   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
3207141Sjeff
4207141SjeffThis file is part of GCC.
5207141Sjeff
6207141SjeffGCC is free software; you can redistribute it and/or modify it
7207141Sjeffunder the terms of the GNU General Public License as published by the
8207141SjeffFree Software Foundation; either version 2, or (at your option) any
9207141Sjefflater version.
10207141Sjeff
11207141SjeffGCC is distributed in the hope that it will be useful, but WITHOUT
12207141SjeffANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13207141SjeffFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14207141Sjefffor more details.
15207141Sjeff
16207141SjeffYou should have received a copy of the GNU General Public License
17207141Sjeffalong with GCC; see the file COPYING.  If not, write to the Free
18207141SjeffSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
19207141Sjeff02110-1301, USA.  */
20207141Sjeff
21207141Sjeff#include "config.h"
22207141Sjeff#include "system.h"
23207141Sjeff#include "coretypes.h"
24207141Sjeff#include "tm.h"
25207141Sjeff#include "ggc.h"
26207141Sjeff#include "tree.h"
27207141Sjeff#include "rtl.h"
28207141Sjeff#include "flags.h"
29207141Sjeff#include "tm_p.h"
30207141Sjeff#include "basic-block.h"
31218604Skib#include "timevar.h"
32207141Sjeff#include "diagnostic.h"
33207141Sjeff#include "tree-flow.h"
34207141Sjeff#include "tree-pass.h"
35207141Sjeff#include "tree-dump.h"
36207141Sjeff#include "langhooks.h"
37207141Sjeff
38207141Sjeffstatic unsigned int tree_ssa_phiopt (void);
39207141Sjeffstatic bool conditional_replacement (basic_block, basic_block,
40207141Sjeff				     edge, edge, tree, tree, tree);
41217769Smckusickstatic bool value_replacement (basic_block, basic_block,
42217769Smckusick			       edge, edge, tree, tree, tree);
43209408Sdelphijstatic bool minmax_replacement (basic_block, basic_block,
44209408Sdelphij				edge, edge, tree, tree, tree);
45207141Sjeffstatic bool abs_replacement (basic_block, basic_block,
46207141Sjeff			     edge, edge, tree, tree, tree);
47207141Sjeffstatic void replace_phi_edge_with_variable (basic_block, edge, tree, tree);
48207141Sjeffstatic basic_block *blocks_in_phiopt_order (void);
49207141Sjeff
50207141Sjeff/* This pass tries to replaces an if-then-else block with an
51209408Sdelphij   assignment.  We have four kinds of transformations.  Some of these
52217769Smckusick   transformations are also performed by the ifcvt RTL optimizer.
53207141Sjeff
54207141Sjeff   Conditional Replacement
55207141Sjeff   -----------------------
56207141Sjeff
57207141Sjeff   This transformation, implemented in conditional_replacement,
58207141Sjeff   replaces
59207141Sjeff
60207141Sjeff     bb0:
61207141Sjeff      if (cond) goto bb2; else goto bb1;
62207141Sjeff     bb1:
63207141Sjeff     bb2:
64207141Sjeff      x = PHI <0 (bb1), 1 (bb0), ...>;
65207141Sjeff
66207141Sjeff   with
67207141Sjeff
68207141Sjeff     bb0:
69207141Sjeff      x' = cond;
70207141Sjeff      goto bb2;
71207141Sjeff     bb2:
72207141Sjeff      x = PHI <x' (bb0), ...>;
73207141Sjeff
74207141Sjeff   We remove bb1 as it becomes unreachable.  This occurs often due to
75207141Sjeff   gimplification of conditionals.
76207141Sjeff
77207141Sjeff   Value Replacement
78207141Sjeff   -----------------
79207141Sjeff
80207141Sjeff   This transformation, implemented in value_replacement, replaces
81207141Sjeff
82207141Sjeff     bb0:
83207141Sjeff       if (a != b) goto bb2; else goto bb1;
84207141Sjeff     bb1:
85207141Sjeff     bb2:
86207141Sjeff       x = PHI <a (bb1), b (bb0), ...>;
87207141Sjeff
88207141Sjeff   with
89207141Sjeff
90207141Sjeff     bb0:
91207141Sjeff     bb2:
92207141Sjeff       x = PHI <b (bb0), ...>;
93207141Sjeff
94207141Sjeff   This opportunity can sometimes occur as a result of other
95207141Sjeff   optimizations.
96207141Sjeff
97207141Sjeff   ABS Replacement
98207141Sjeff   ---------------
99207141Sjeff
100207141Sjeff   This transformation, implemented in abs_replacement, replaces
101207141Sjeff
102207141Sjeff     bb0:
103207141Sjeff       if (a >= 0) goto bb2; else goto bb1;
104207141Sjeff     bb1:
105207141Sjeff       x = -a;
106207141Sjeff     bb2:
107207141Sjeff       x = PHI <x (bb1), a (bb0), ...>;
108207141Sjeff
109207141Sjeff   with
110207141Sjeff
111207141Sjeff     bb0:
112207141Sjeff       x' = ABS_EXPR< a >;
113207141Sjeff     bb2:
114207141Sjeff       x = PHI <x' (bb0), ...>;
115207141Sjeff
116207141Sjeff   MIN/MAX Replacement
117207141Sjeff   -------------------
118207141Sjeff
119207141Sjeff   This transformation, minmax_replacement replaces
120207141Sjeff
121207141Sjeff     bb0:
122207141Sjeff       if (a <= b) goto bb2; else goto bb1;
123207141Sjeff     bb1:
124207141Sjeff     bb2:
125207141Sjeff       x = PHI <b (bb1), a (bb0), ...>;
126207141Sjeff
127207141Sjeff   with
128207141Sjeff
129207141Sjeff     bb0:
130207141Sjeff       x' = MIN_EXPR (a, b)
131207141Sjeff     bb2:
132207141Sjeff       x = PHI <x' (bb0), ...>;
133207141Sjeff
134207141Sjeff   A similar transformation is done for MAX_EXPR.  */
135207141Sjeff
136207141Sjeffstatic unsigned int
137207141Sjefftree_ssa_phiopt (void)
138207141Sjeff{
139207141Sjeff  basic_block bb;
140207141Sjeff  basic_block *bb_order;
141207141Sjeff  unsigned n, i;
142207141Sjeff  bool cfgchanged = false;
143207141Sjeff
144207141Sjeff  /* Search every basic block for COND_EXPR we may be able to optimize.
145207141Sjeff
146207141Sjeff     We walk the blocks in order that guarantees that a block with
147207141Sjeff     a single predecessor is processed before the predecessor.
148207141Sjeff     This ensures that we collapse inner ifs before visiting the
149209408Sdelphij     outer ones, and also that we do not try to visit a removed
150209408Sdelphij     block.  */
151207141Sjeff  bb_order = blocks_in_phiopt_order ();
152209408Sdelphij  n = n_basic_blocks - NUM_FIXED_BLOCKS;
153207141Sjeff
154207141Sjeff  for (i = 0; i < n; i++)
155207141Sjeff    {
156207141Sjeff      tree cond_expr;
157207141Sjeff      tree phi;
158207141Sjeff      basic_block bb1, bb2;
159207141Sjeff      edge e1, e2;
160207141Sjeff      tree arg0, arg1;
161207141Sjeff
162207141Sjeff      bb = bb_order[i];
163207141Sjeff
164207141Sjeff      cond_expr = last_stmt (bb);
165207141Sjeff      /* Check to see if the last statement is a COND_EXPR.  */
166209408Sdelphij      if (!cond_expr
167207141Sjeff          || TREE_CODE (cond_expr) != COND_EXPR)
168207141Sjeff        continue;
169207141Sjeff
170207141Sjeff      e1 = EDGE_SUCC (bb, 0);
171209408Sdelphij      bb1 = e1->dest;
172209408Sdelphij      e2 = EDGE_SUCC (bb, 1);
173209408Sdelphij      bb2 = e2->dest;
174209408Sdelphij
175209408Sdelphij      /* We cannot do the optimization on abnormal edges.  */
176209408Sdelphij      if ((e1->flags & EDGE_ABNORMAL) != 0
177209408Sdelphij          || (e2->flags & EDGE_ABNORMAL) != 0)
178209408Sdelphij       continue;
179209408Sdelphij
180209408Sdelphij      /* If either bb1's succ or bb2 or bb2's succ is non NULL.  */
181209408Sdelphij      if (EDGE_COUNT (bb1->succs) == 0
182209408Sdelphij          || bb2 == NULL
183209408Sdelphij	  || EDGE_COUNT (bb2->succs) == 0)
184209408Sdelphij        continue;
185209408Sdelphij
186209408Sdelphij      /* Find the bb which is the fall through to the other.  */
187209408Sdelphij      if (EDGE_SUCC (bb1, 0)->dest == bb2)
188209408Sdelphij        ;
189209408Sdelphij      else if (EDGE_SUCC (bb2, 0)->dest == bb1)
190207141Sjeff        {
191207141Sjeff	  basic_block bb_tmp = bb1;
192207141Sjeff	  edge e_tmp = e1;
193207141Sjeff	  bb1 = bb2;
194207141Sjeff	  bb2 = bb_tmp;
195207141Sjeff	  e1 = e2;
196207141Sjeff	  e2 = e_tmp;
197207141Sjeff	}
198207141Sjeff      else
199209408Sdelphij        continue;
200207141Sjeff
201209408Sdelphij      e1 = EDGE_SUCC (bb1, 0);
202207141Sjeff
203207141Sjeff      /* Make sure that bb1 is just a fall through.  */
204207141Sjeff      if (!single_succ_p (bb1)
205218604Skib	  || (e1->flags & EDGE_FALLTHRU) == 0)
206218604Skib        continue;
207218604Skib
208218604Skib      /* Also make sure that bb1 only have one predecessor and that it
209218604Skib	 is bb.  */
210207141Sjeff      if (!single_pred_p (bb1)
211207141Sjeff          || single_pred (bb1) != bb)
212207141Sjeff	continue;
213207141Sjeff
214207141Sjeff      phi = phi_nodes (bb2);
215207141Sjeff
216207141Sjeff      /* Check to make sure that there is only one PHI node.
217207141Sjeff         TODO: we could do it with more than one iff the other PHI nodes
218207141Sjeff	 have the same elements for these two edges.  */
219207141Sjeff      if (!phi || PHI_CHAIN (phi) != NULL)
220207141Sjeff	continue;
221207141Sjeff
222207141Sjeff      arg0 = PHI_ARG_DEF_TREE (phi, e1->dest_idx);
223207141Sjeff      arg1 = PHI_ARG_DEF_TREE (phi, e2->dest_idx);
224207141Sjeff
225207141Sjeff      /* Something is wrong if we cannot find the arguments in the PHI
226207141Sjeff	 node.  */
227207141Sjeff      gcc_assert (arg0 != NULL && arg1 != NULL);
228207141Sjeff
229207141Sjeff      /* Do the replacement of conditional if it can be done.  */
230207141Sjeff      if (conditional_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
231207141Sjeff	cfgchanged = true;
232207141Sjeff      else if (value_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
233207141Sjeff	cfgchanged = true;
234207141Sjeff      else if (abs_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
235207141Sjeff	cfgchanged = true;
236207141Sjeff      else if (minmax_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
237207141Sjeff	cfgchanged = true;
238209408Sdelphij    }
239207141Sjeff
240209408Sdelphij  free (bb_order);
241207141Sjeff
242207141Sjeff  /* If the CFG has changed, we should cleanup the CFG. */
243207141Sjeff  return cfgchanged ? TODO_cleanup_cfg : 0;
244207141Sjeff}
245207141Sjeff
246207141Sjeff/* Returns the list of basic blocks in the function in an order that guarantees
247207141Sjeff   that if a block X has just a single predecessor Y, then Y is after X in the
248207141Sjeff   ordering.  */
249207141Sjeff
250207141Sjeffstatic basic_block *
251207141Sjeffblocks_in_phiopt_order (void)
252207141Sjeff{
253207141Sjeff  basic_block x, y;
254207141Sjeff  basic_block *order = XNEWVEC (basic_block, n_basic_blocks);
255207141Sjeff  unsigned n = n_basic_blocks - NUM_FIXED_BLOCKS;
256209408Sdelphij  unsigned np, i;
257209408Sdelphij  sbitmap visited = sbitmap_alloc (last_basic_block);
258207141Sjeff
259207141Sjeff#define MARK_VISITED(BB) (SET_BIT (visited, (BB)->index))
260207141Sjeff#define VISITED_P(BB) (TEST_BIT (visited, (BB)->index))
261207141Sjeff
262207141Sjeff  sbitmap_zero (visited);
263207141Sjeff
264207141Sjeff  MARK_VISITED (ENTRY_BLOCK_PTR);
265207141Sjeff  FOR_EACH_BB (x)
266207141Sjeff    {
267207141Sjeff      if (VISITED_P (x))
268207141Sjeff	continue;
269207141Sjeff
270207141Sjeff      /* Walk the predecessors of x as long as they have precisely one
271207141Sjeff	 predecessor and add them to the list, so that they get stored
272207141Sjeff	 after x.  */
273207141Sjeff      for (y = x, np = 1;
274209408Sdelphij	   single_pred_p (y) && !VISITED_P (single_pred (y));
275207141Sjeff	   y = single_pred (y))
276207141Sjeff	np++;
277207141Sjeff      for (y = x, i = n - np;
278207141Sjeff	   single_pred_p (y) && !VISITED_P (single_pred (y));
279207141Sjeff	   y = single_pred (y), i++)
280207141Sjeff	{
281207141Sjeff	  order[i] = y;
282207141Sjeff	  MARK_VISITED (y);
283207141Sjeff	}
284207141Sjeff      order[i] = y;
285207141Sjeff      MARK_VISITED (y);
286207141Sjeff
287207141Sjeff      gcc_assert (i == n - 1);
288207141Sjeff      n -= np;
289207141Sjeff    }
290207141Sjeff
291207141Sjeff  sbitmap_free (visited);
292207141Sjeff  gcc_assert (n == 0);
293207141Sjeff  return order;
294207141Sjeff
295207141Sjeff#undef MARK_VISITED
296207141Sjeff#undef VISITED_P
297207141Sjeff}
298207141Sjeff
299207141Sjeff/* Return TRUE if block BB has no executable statements, otherwise return
300207141Sjeff   FALSE.  */
301207141Sjeffbool
302207141Sjeffempty_block_p (basic_block bb)
303207141Sjeff{
304207141Sjeff  block_stmt_iterator bsi;
305207141Sjeff
306207141Sjeff  /* BB must have no executable statements.  */
307207141Sjeff  bsi = bsi_start (bb);
308207141Sjeff  while (!bsi_end_p (bsi)
309207141Sjeff	  && (TREE_CODE (bsi_stmt (bsi)) == LABEL_EXPR
310207141Sjeff	      || IS_EMPTY_STMT (bsi_stmt (bsi))))
311207141Sjeff    bsi_next (&bsi);
312207141Sjeff
313207141Sjeff  if (!bsi_end_p (bsi))
314207141Sjeff    return false;
315207141Sjeff
316207141Sjeff  return true;
317207141Sjeff}
318207141Sjeff
319207141Sjeff/* Replace PHI node element whose edge is E in block BB with variable NEW.
320207141Sjeff   Remove the edge from COND_BLOCK which does not lead to BB (COND_BLOCK
321207141Sjeff   is known to have two edges, one of which must reach BB).  */
322207141Sjeff
323207141Sjeffstatic void
324207141Sjeffreplace_phi_edge_with_variable (basic_block cond_block,
325207141Sjeff				edge e, tree phi, tree new)
326207141Sjeff{
327207141Sjeff  basic_block bb = bb_for_stmt (phi);
328207141Sjeff  basic_block block_to_remove;
329207141Sjeff  block_stmt_iterator bsi;
330207141Sjeff
331207141Sjeff  /* Change the PHI argument to new.  */
332207141Sjeff  SET_USE (PHI_ARG_DEF_PTR (phi, e->dest_idx), new);
333207141Sjeff
334207141Sjeff  /* Remove the empty basic block.  */
335207141Sjeff  if (EDGE_SUCC (cond_block, 0)->dest == bb)
336207141Sjeff    {
337207141Sjeff      EDGE_SUCC (cond_block, 0)->flags |= EDGE_FALLTHRU;
338207141Sjeff      EDGE_SUCC (cond_block, 0)->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
339207141Sjeff      EDGE_SUCC (cond_block, 0)->probability = REG_BR_PROB_BASE;
340207141Sjeff      EDGE_SUCC (cond_block, 0)->count += EDGE_SUCC (cond_block, 1)->count;
341207141Sjeff
342207141Sjeff      block_to_remove = EDGE_SUCC (cond_block, 1)->dest;
343207141Sjeff    }
344207141Sjeff  else
345207141Sjeff    {
346207141Sjeff      EDGE_SUCC (cond_block, 1)->flags |= EDGE_FALLTHRU;
347207141Sjeff      EDGE_SUCC (cond_block, 1)->flags
348207141Sjeff	&= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
349207141Sjeff      EDGE_SUCC (cond_block, 1)->probability = REG_BR_PROB_BASE;
350207141Sjeff      EDGE_SUCC (cond_block, 1)->count += EDGE_SUCC (cond_block, 0)->count;
351207141Sjeff
352207141Sjeff      block_to_remove = EDGE_SUCC (cond_block, 0)->dest;
353207141Sjeff    }
354207141Sjeff  delete_basic_block (block_to_remove);
355207141Sjeff
356207141Sjeff  /* Eliminate the COND_EXPR at the end of COND_BLOCK.  */
357207141Sjeff  bsi = bsi_last (cond_block);
358207141Sjeff  bsi_remove (&bsi, true);
359207141Sjeff
360207141Sjeff  if (dump_file && (dump_flags & TDF_DETAILS))
361207141Sjeff    fprintf (dump_file,
362207141Sjeff	      "COND_EXPR in block %d and PHI in block %d converted to straightline code.\n",
363207141Sjeff	      cond_block->index,
364207141Sjeff	      bb->index);
365207141Sjeff}
366207141Sjeff
367207141Sjeff/*  The function conditional_replacement does the main work of doing the
368207141Sjeff    conditional replacement.  Return true if the replacement is done.
369207141Sjeff    Otherwise return false.
370207141Sjeff    BB is the basic block where the replacement is going to be done on.  ARG0
371207141Sjeff    is argument 0 from PHI.  Likewise for ARG1.  */
372207141Sjeff
373207141Sjeffstatic bool
374207141Sjeffconditional_replacement (basic_block cond_bb, basic_block middle_bb,
375207141Sjeff			 edge e0, edge e1, tree phi,
376207141Sjeff			 tree arg0, tree arg1)
377209408Sdelphij{
378207141Sjeff  tree result;
379207141Sjeff  tree old_result = NULL;
380207141Sjeff  tree new, cond;
381207141Sjeff  block_stmt_iterator bsi;
382207141Sjeff  edge true_edge, false_edge;
383207141Sjeff  tree new_var = NULL;
384207141Sjeff  tree new_var1;
385207141Sjeff
386207141Sjeff  /* The PHI arguments have the constants 0 and 1, then convert
387207141Sjeff     it to the conditional.  */
388207141Sjeff  if ((integer_zerop (arg0) && integer_onep (arg1))
389207141Sjeff      || (integer_zerop (arg1) && integer_onep (arg0)))
390207141Sjeff    ;
391207141Sjeff  else
392207141Sjeff    return false;
393207141Sjeff
394207141Sjeff  if (!empty_block_p (middle_bb))
395207141Sjeff    return false;
396207141Sjeff
397207141Sjeff  /* If the condition is not a naked SSA_NAME and its type does not
398207141Sjeff     match the type of the result, then we have to create a new
399207141Sjeff     variable to optimize this case as it would likely create
400207141Sjeff     non-gimple code when the condition was converted to the
401207141Sjeff     result's type.  */
402207141Sjeff  cond = COND_EXPR_COND (last_stmt (cond_bb));
403209408Sdelphij  result = PHI_RESULT (phi);
404207141Sjeff  if (TREE_CODE (cond) != SSA_NAME
405207141Sjeff      && !lang_hooks.types_compatible_p (TREE_TYPE (cond), TREE_TYPE (result)))
406207141Sjeff    {
407207141Sjeff      tree tmp;
408207141Sjeff
409207141Sjeff      if (!COMPARISON_CLASS_P (cond))
410207141Sjeff	return false;
411207141Sjeff
412207141Sjeff      tmp = create_tmp_var (TREE_TYPE (cond), NULL);
413207141Sjeff      add_referenced_var (tmp);
414207141Sjeff      new_var = make_ssa_name (tmp, NULL);
415207141Sjeff      old_result = cond;
416207141Sjeff      cond = new_var;
417207141Sjeff    }
418207141Sjeff
419207141Sjeff  /* If the condition was a naked SSA_NAME and the type is not the
420207141Sjeff     same as the type of the result, then convert the type of the
421207141Sjeff     condition.  */
422207141Sjeff  if (!lang_hooks.types_compatible_p (TREE_TYPE (cond), TREE_TYPE (result)))
423207141Sjeff    cond = fold_convert (TREE_TYPE (result), cond);
424207141Sjeff
425207141Sjeff  /* We need to know which is the true edge and which is the false
426207141Sjeff     edge so that we know when to invert the condition below.  */
427207141Sjeff  extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge);
428207141Sjeff
429207141Sjeff  /* Insert our new statement at the end of conditional block before the
430207141Sjeff     COND_EXPR.  */
431207141Sjeff  bsi = bsi_last (cond_bb);
432207141Sjeff  bsi_insert_before (&bsi, build_empty_stmt (), BSI_NEW_STMT);
433207141Sjeff
434207141Sjeff  if (old_result)
435207141Sjeff    {
436209408Sdelphij      tree new1;
437207141Sjeff
438207141Sjeff      new1 = build2 (TREE_CODE (old_result), TREE_TYPE (old_result),
439207141Sjeff		     TREE_OPERAND (old_result, 0),
440207141Sjeff		     TREE_OPERAND (old_result, 1));
441207141Sjeff
442207141Sjeff      new1 = build2 (MODIFY_EXPR, TREE_TYPE (old_result), new_var, new1);
443207141Sjeff      SSA_NAME_DEF_STMT (new_var) = new1;
444207141Sjeff
445207141Sjeff      bsi_insert_after (&bsi, new1, BSI_NEW_STMT);
446207141Sjeff    }
447207141Sjeff
448207141Sjeff  new_var1 = duplicate_ssa_name (PHI_RESULT (phi), NULL);
449207141Sjeff
450207141Sjeff
451207141Sjeff  /* At this point we know we have a COND_EXPR with two successors.
452207141Sjeff     One successor is BB, the other successor is an empty block which
453207141Sjeff     falls through into BB.
454207141Sjeff
455207141Sjeff     There is a single PHI node at the join point (BB) and its arguments
456207141Sjeff     are constants (0, 1).
457207141Sjeff
458207141Sjeff     So, given the condition COND, and the two PHI arguments, we can
459207141Sjeff     rewrite this PHI into non-branching code:
460207141Sjeff
461207141Sjeff       dest = (COND) or dest = COND'
462207141Sjeff
463207141Sjeff     We use the condition as-is if the argument associated with the
464207141Sjeff     true edge has the value one or the argument associated with the
465207141Sjeff     false edge as the value zero.  Note that those conditions are not
466207141Sjeff     the same since only one of the outgoing edges from the COND_EXPR
467207141Sjeff     will directly reach BB and thus be associated with an argument.  */
468207141Sjeff  if ((e0 == true_edge && integer_onep (arg0))
469207141Sjeff      || (e0 == false_edge && integer_zerop (arg0))
470207141Sjeff      || (e1 == true_edge && integer_onep (arg1))
471207141Sjeff      || (e1 == false_edge && integer_zerop (arg1)))
472207141Sjeff    {
473207141Sjeff      new = build2 (MODIFY_EXPR, TREE_TYPE (new_var1), new_var1, cond);
474207141Sjeff    }
475207141Sjeff  else
476207141Sjeff    {
477207141Sjeff      tree cond1 = invert_truthvalue (cond);
478207141Sjeff
479207141Sjeff      cond = cond1;
480209408Sdelphij
481207141Sjeff      /* If what we get back is a conditional expression, there is no
482207141Sjeff	  way that it can be gimple.  */
483207141Sjeff      if (TREE_CODE (cond) == COND_EXPR)
484207141Sjeff	{
485207141Sjeff	  release_ssa_name (new_var1);
486207141Sjeff	  return false;
487207141Sjeff	}
488207141Sjeff
489207141Sjeff      /* If COND is not something we can expect to be reducible to a GIMPLE
490207141Sjeff	 condition, return early.  */
491207141Sjeff      if (is_gimple_cast (cond))
492207141Sjeff	cond1 = TREE_OPERAND (cond, 0);
493207141Sjeff      if (TREE_CODE (cond1) == TRUTH_NOT_EXPR
494207141Sjeff	  && !is_gimple_val (TREE_OPERAND (cond1, 0)))
495207141Sjeff	{
496207141Sjeff	  release_ssa_name (new_var1);
497207141Sjeff	  return false;
498207141Sjeff	}
499207141Sjeff
500207141Sjeff      /* If what we get back is not gimple try to create it as gimple by
501207141Sjeff	 using a temporary variable.  */
502207141Sjeff      if (is_gimple_cast (cond)
503207141Sjeff	  && !is_gimple_val (TREE_OPERAND (cond, 0)))
504207141Sjeff	{
505207141Sjeff	  tree op0, tmp, cond_tmp;
506207141Sjeff
507207141Sjeff	  /* Only "real" casts are OK here, not everything that is
508207141Sjeff	     acceptable to is_gimple_cast.  Make sure we don't do
509207141Sjeff	     anything stupid here.  */
510207141Sjeff	  gcc_assert (TREE_CODE (cond) == NOP_EXPR
511207141Sjeff		      || TREE_CODE (cond) == CONVERT_EXPR);
512207141Sjeff
513207141Sjeff	  op0 = TREE_OPERAND (cond, 0);
514207141Sjeff	  tmp = create_tmp_var (TREE_TYPE (op0), NULL);
515207141Sjeff	  add_referenced_var (tmp);
516207141Sjeff	  cond_tmp = make_ssa_name (tmp, NULL);
517207141Sjeff	  new = build2 (MODIFY_EXPR, TREE_TYPE (cond_tmp), cond_tmp, op0);
518207141Sjeff	  SSA_NAME_DEF_STMT (cond_tmp) = new;
519207141Sjeff
520207141Sjeff	  bsi_insert_after (&bsi, new, BSI_NEW_STMT);
521207141Sjeff	  cond = fold_convert (TREE_TYPE (result), cond_tmp);
522207141Sjeff	}
523207141Sjeff
524207141Sjeff      new = build2 (MODIFY_EXPR, TREE_TYPE (new_var1), new_var1, cond);
525221110Sdes    }
526207141Sjeff
527207141Sjeff  bsi_insert_after (&bsi, new, BSI_NEW_STMT);
528207141Sjeff
529207141Sjeff  SSA_NAME_DEF_STMT (new_var1) = new;
530207141Sjeff
531207141Sjeff  replace_phi_edge_with_variable (cond_bb, e1, phi, new_var1);
532207141Sjeff
533207141Sjeff  /* Note that we optimized this PHI.  */
534207141Sjeff  return true;
535207141Sjeff}
536207141Sjeff
537207141Sjeff/*  The function value_replacement does the main work of doing the value
538207141Sjeff    replacement.  Return true if the replacement is done.  Otherwise return
539207141Sjeff    false.
540207141Sjeff    BB is the basic block where the replacement is going to be done on.  ARG0
541207141Sjeff    is argument 0 from the PHI.  Likewise for ARG1.  */
542207141Sjeff
543207141Sjeffstatic bool
544207141Sjeffvalue_replacement (basic_block cond_bb, basic_block middle_bb,
545207141Sjeff		   edge e0, edge e1, tree phi,
546207141Sjeff		   tree arg0, tree arg1)
547207141Sjeff{
548207141Sjeff  tree cond;
549207141Sjeff  edge true_edge, false_edge;
550207141Sjeff
551207141Sjeff  /* If the type says honor signed zeros we cannot do this
552207141Sjeff     optimization.  */
553207141Sjeff  if (HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
554207141Sjeff    return false;
555207141Sjeff
556207141Sjeff  if (!empty_block_p (middle_bb))
557221110Sdes    return false;
558207141Sjeff
559207141Sjeff  cond = COND_EXPR_COND (last_stmt (cond_bb));
560207141Sjeff
561207141Sjeff  /* This transformation is only valid for equality comparisons.  */
562207141Sjeff  if (TREE_CODE (cond) != NE_EXPR && TREE_CODE (cond) != EQ_EXPR)
563207141Sjeff    return false;
564207141Sjeff
565207141Sjeff  /* We need to know which is the true edge and which is the false
566207141Sjeff      edge so that we know if have abs or negative abs.  */
567207141Sjeff  extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge);
568207141Sjeff
569207141Sjeff  /* At this point we know we have a COND_EXPR with two successors.
570207141Sjeff     One successor is BB, the other successor is an empty block which
571207141Sjeff     falls through into BB.
572207141Sjeff
573207141Sjeff     The condition for the COND_EXPR is known to be NE_EXPR or EQ_EXPR.
574207141Sjeff
575207141Sjeff     There is a single PHI node at the join point (BB) with two arguments.
576207141Sjeff
577207141Sjeff     We now need to verify that the two arguments in the PHI node match
578207141Sjeff     the two arguments to the equality comparison.  */
579221110Sdes
580207141Sjeff  if ((operand_equal_for_phi_arg_p (arg0, TREE_OPERAND (cond, 0))
581207141Sjeff       && operand_equal_for_phi_arg_p (arg1, TREE_OPERAND (cond, 1)))
582207141Sjeff      || (operand_equal_for_phi_arg_p (arg1, TREE_OPERAND (cond, 0))
583207141Sjeff	  && operand_equal_for_phi_arg_p (arg0, TREE_OPERAND (cond, 1))))
584207141Sjeff    {
585207141Sjeff      edge e;
586207141Sjeff      tree arg;
587207141Sjeff
588207141Sjeff      /* For NE_EXPR, we want to build an assignment result = arg where
589207141Sjeff	 arg is the PHI argument associated with the true edge.  For
590207141Sjeff	 EQ_EXPR we want the PHI argument associated with the false edge.  */
591207141Sjeff      e = (TREE_CODE (cond) == NE_EXPR ? true_edge : false_edge);
592207141Sjeff
593207141Sjeff      /* Unfortunately, E may not reach BB (it may instead have gone to
594207141Sjeff	 OTHER_BLOCK).  If that is the case, then we want the single outgoing
595207141Sjeff	 edge from OTHER_BLOCK which reaches BB and represents the desired
596207141Sjeff	 path from COND_BLOCK.  */
597207141Sjeff      if (e->dest == middle_bb)
598207141Sjeff	e = single_succ_edge (e->dest);
599207141Sjeff
600207141Sjeff      /* Now we know the incoming edge to BB that has the argument for the
601207141Sjeff	 RHS of our new assignment statement.  */
602207141Sjeff      if (e0 == e)
603207141Sjeff	arg = arg0;
604207141Sjeff      else
605207141Sjeff	arg = arg1;
606207141Sjeff
607207141Sjeff      replace_phi_edge_with_variable (cond_bb, e1, phi, arg);
608207141Sjeff
609207141Sjeff      /* Note that we optimized this PHI.  */
610207141Sjeff      return true;
611207141Sjeff    }
612207141Sjeff  return false;
613207141Sjeff}
614207141Sjeff
615207141Sjeff/*  The function minmax_replacement does the main work of doing the minmax
616207141Sjeff    replacement.  Return true if the replacement is done.  Otherwise return
617207141Sjeff    false.
618207141Sjeff    BB is the basic block where the replacement is going to be done on.  ARG0
619207141Sjeff    is argument 0 from the PHI.  Likewise for ARG1.  */
620207141Sjeff
621207141Sjeffstatic bool
622207141Sjeffminmax_replacement (basic_block cond_bb, basic_block middle_bb,
623207141Sjeff		    edge e0, edge e1, tree phi,
624207141Sjeff		    tree arg0, tree arg1)
625207141Sjeff{
626207141Sjeff  tree result, type;
627207141Sjeff  tree cond, new;
628207141Sjeff  edge true_edge, false_edge;
629207141Sjeff  enum tree_code cmp, minmax, ass_code;
630207141Sjeff  tree smaller, larger, arg_true, arg_false;
631207141Sjeff  block_stmt_iterator bsi, bsi_from;
632207141Sjeff
633207141Sjeff  type = TREE_TYPE (PHI_RESULT (phi));
634207141Sjeff
635207141Sjeff  /* The optimization may be unsafe due to NaNs.  */
636207141Sjeff  if (HONOR_NANS (TYPE_MODE (type)))
637207141Sjeff    return false;
638207141Sjeff
639207141Sjeff  cond = COND_EXPR_COND (last_stmt (cond_bb));
640207141Sjeff  cmp = TREE_CODE (cond);
641207141Sjeff  result = PHI_RESULT (phi);
642207141Sjeff
643207141Sjeff  /* This transformation is only valid for order comparisons.  Record which
644207141Sjeff     operand is smaller/larger if the result of the comparison is true.  */
645207141Sjeff  if (cmp == LT_EXPR || cmp == LE_EXPR)
646207141Sjeff    {
647207141Sjeff      smaller = TREE_OPERAND (cond, 0);
648207141Sjeff      larger = TREE_OPERAND (cond, 1);
649207141Sjeff    }
650207141Sjeff  else if (cmp == GT_EXPR || cmp == GE_EXPR)
651207141Sjeff    {
652207141Sjeff      smaller = TREE_OPERAND (cond, 1);
653207141Sjeff      larger = TREE_OPERAND (cond, 0);
654207141Sjeff    }
655207141Sjeff  else
656207141Sjeff    return false;
657207141Sjeff
658207141Sjeff  /* We need to know which is the true edge and which is the false
659207141Sjeff      edge so that we know if have abs or negative abs.  */
660207141Sjeff  extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge);
661207141Sjeff
662207141Sjeff  /* Forward the edges over the middle basic block.  */
663207141Sjeff  if (true_edge->dest == middle_bb)
664207141Sjeff    true_edge = EDGE_SUCC (true_edge->dest, 0);
665207141Sjeff  if (false_edge->dest == middle_bb)
666207141Sjeff    false_edge = EDGE_SUCC (false_edge->dest, 0);
667207141Sjeff
668207141Sjeff  if (true_edge == e0)
669207141Sjeff    {
670207141Sjeff      gcc_assert (false_edge == e1);
671207141Sjeff      arg_true = arg0;
672207141Sjeff      arg_false = arg1;
673207141Sjeff    }
674207141Sjeff  else
675207141Sjeff    {
676207141Sjeff      gcc_assert (false_edge == e0);
677207141Sjeff      gcc_assert (true_edge == e1);
678207141Sjeff      arg_true = arg1;
679207141Sjeff      arg_false = arg0;
680207141Sjeff    }
681207141Sjeff
682207141Sjeff  if (empty_block_p (middle_bb))
683207141Sjeff    {
684207141Sjeff      if (operand_equal_for_phi_arg_p (arg_true, smaller)
685207141Sjeff	  && operand_equal_for_phi_arg_p (arg_false, larger))
686207141Sjeff	{
687207141Sjeff	  /* Case
688207141Sjeff
689207141Sjeff	     if (smaller < larger)
690207141Sjeff	     rslt = smaller;
691207141Sjeff	     else
692207141Sjeff	     rslt = larger;  */
693207141Sjeff	  minmax = MIN_EXPR;
694207141Sjeff	}
695207141Sjeff      else if (operand_equal_for_phi_arg_p (arg_false, smaller)
696207141Sjeff	       && operand_equal_for_phi_arg_p (arg_true, larger))
697207141Sjeff	minmax = MAX_EXPR;
698207141Sjeff      else
699207141Sjeff	return false;
700207141Sjeff    }
701207141Sjeff  else
702207141Sjeff    {
703207141Sjeff      /* Recognize the following case, assuming d <= u:
704207141Sjeff
705207141Sjeff	 if (a <= u)
706207141Sjeff	   b = MAX (a, d);
707207141Sjeff	 x = PHI <b, u>
708207141Sjeff
709207141Sjeff	 This is equivalent to
710207141Sjeff
711207141Sjeff	 b = MAX (a, d);
712209408Sdelphij	 x = MIN (b, u);  */
713207141Sjeff
714209408Sdelphij      tree assign = last_and_only_stmt (middle_bb);
715207141Sjeff      tree lhs, rhs, op0, op1, bound;
716207141Sjeff
717207141Sjeff      if (!assign
718207141Sjeff	  || TREE_CODE (assign) != MODIFY_EXPR)
719207141Sjeff	return false;
720207141Sjeff
721221110Sdes      lhs = TREE_OPERAND (assign, 0);
722207141Sjeff      rhs = TREE_OPERAND (assign, 1);
723207141Sjeff      ass_code = TREE_CODE (rhs);
724207141Sjeff      if (ass_code != MAX_EXPR && ass_code != MIN_EXPR)
725207141Sjeff	return false;
726209408Sdelphij      op0 = TREE_OPERAND (rhs, 0);
727207141Sjeff      op1 = TREE_OPERAND (rhs, 1);
728207141Sjeff
729207141Sjeff      if (true_edge->src == middle_bb)
730207141Sjeff	{
731207141Sjeff	  /* We got here if the condition is true, i.e., SMALLER < LARGER.  */
732207141Sjeff	  if (!operand_equal_for_phi_arg_p (lhs, arg_true))
733207141Sjeff	    return false;
734207141Sjeff
735207141Sjeff	  if (operand_equal_for_phi_arg_p (arg_false, larger))
736207141Sjeff	    {
737207141Sjeff	      /* Case
738209408Sdelphij
739209408Sdelphij		 if (smaller < larger)
740207141Sjeff		   {
741207141Sjeff		     r' = MAX_EXPR (smaller, bound)
742207141Sjeff		   }
743207141Sjeff		 r = PHI <r', larger>  --> to be turned to MIN_EXPR.  */
744207141Sjeff	      if (ass_code != MAX_EXPR)
745207141Sjeff		return false;
746207141Sjeff
747207141Sjeff	      minmax = MIN_EXPR;
748207141Sjeff	      if (operand_equal_for_phi_arg_p (op0, smaller))
749207141Sjeff		bound = op1;
750207141Sjeff	      else if (operand_equal_for_phi_arg_p (op1, smaller))
751207141Sjeff		bound = op0;
752207141Sjeff	      else
753207141Sjeff		return false;
754207141Sjeff
755207141Sjeff	      /* We need BOUND <= LARGER.  */
756207141Sjeff	      if (!integer_nonzerop (fold_build2 (LE_EXPR, boolean_type_node,
757207141Sjeff						  bound, larger)))
758207141Sjeff		return false;
759207141Sjeff	    }
760207141Sjeff	  else if (operand_equal_for_phi_arg_p (arg_false, smaller))
761207141Sjeff	    {
762207141Sjeff	      /* Case
763207141Sjeff
764207141Sjeff		 if (smaller < larger)
765207141Sjeff		   {
766207141Sjeff		     r' = MIN_EXPR (larger, bound)
767207141Sjeff		   }
768207141Sjeff		 r = PHI <r', smaller>  --> to be turned to MAX_EXPR.  */
769207141Sjeff	      if (ass_code != MIN_EXPR)
770207141Sjeff		return false;
771207141Sjeff
772207141Sjeff	      minmax = MAX_EXPR;
773207141Sjeff	      if (operand_equal_for_phi_arg_p (op0, larger))
774207141Sjeff		bound = op1;
775207141Sjeff	      else if (operand_equal_for_phi_arg_p (op1, larger))
776207141Sjeff		bound = op0;
777207141Sjeff	      else
778207141Sjeff		return false;
779207141Sjeff
780207141Sjeff	      /* We need BOUND >= SMALLER.  */
781207141Sjeff	      if (!integer_nonzerop (fold_build2 (GE_EXPR, boolean_type_node,
782207141Sjeff						  bound, smaller)))
783207141Sjeff		return false;
784207141Sjeff	    }
785207141Sjeff	  else
786207141Sjeff	    return false;
787207141Sjeff	}
788207141Sjeff      else
789207141Sjeff	{
790207141Sjeff	  /* We got here if the condition is false, i.e., SMALLER > LARGER.  */
791207141Sjeff	  if (!operand_equal_for_phi_arg_p (lhs, arg_false))
792207141Sjeff	    return false;
793209408Sdelphij
794209408Sdelphij	  if (operand_equal_for_phi_arg_p (arg_true, larger))
795207141Sjeff	    {
796207141Sjeff	      /* Case
797207141Sjeff
798207141Sjeff		 if (smaller > larger)
799207141Sjeff		   {
800207141Sjeff		     r' = MIN_EXPR (smaller, bound)
801207141Sjeff		   }
802207141Sjeff		 r = PHI <r', larger>  --> to be turned to MAX_EXPR.  */
803207141Sjeff	      if (ass_code != MIN_EXPR)
804207141Sjeff		return false;
805207141Sjeff
806207141Sjeff	      minmax = MAX_EXPR;
807207141Sjeff	      if (operand_equal_for_phi_arg_p (op0, smaller))
808207141Sjeff		bound = op1;
809207141Sjeff	      else if (operand_equal_for_phi_arg_p (op1, smaller))
810207141Sjeff		bound = op0;
811207141Sjeff	      else
812207141Sjeff		return false;
813207141Sjeff
814207141Sjeff	      /* We need BOUND >= LARGER.  */
815207141Sjeff	      if (!integer_nonzerop (fold_build2 (GE_EXPR, boolean_type_node,
816207141Sjeff						  bound, larger)))
817207141Sjeff		return false;
818209716Sjeff	    }
819209716Sjeff	  else if (operand_equal_for_phi_arg_p (arg_true, smaller))
820209716Sjeff	    {
821209716Sjeff	      /* Case
822209716Sjeff
823209716Sjeff		 if (smaller > larger)
824209716Sjeff		   {
825209716Sjeff		     r' = MAX_EXPR (larger, bound)
826209716Sjeff		   }
827209716Sjeff		 r = PHI <r', smaller>  --> to be turned to MIN_EXPR.  */
828209716Sjeff	      if (ass_code != MAX_EXPR)
829209716Sjeff		return false;
830209716Sjeff
831209716Sjeff	      minmax = MIN_EXPR;
832209716Sjeff	      if (operand_equal_for_phi_arg_p (op0, larger))
833209716Sjeff		bound = op1;
834209716Sjeff	      else if (operand_equal_for_phi_arg_p (op1, larger))
835209716Sjeff		bound = op0;
836209716Sjeff	      else
837209716Sjeff		return false;
838209716Sjeff
839209716Sjeff	      /* We need BOUND <= SMALLER.  */
840209716Sjeff	      if (!integer_nonzerop (fold_build2 (LE_EXPR, boolean_type_node,
841209716Sjeff						  bound, smaller)))
842209716Sjeff		return false;
843209716Sjeff	    }
844209716Sjeff	  else
845209716Sjeff	    return false;
846209716Sjeff	}
847209716Sjeff
848209716Sjeff      /* Move the statement from the middle block.  */
849209716Sjeff      bsi = bsi_last (cond_bb);
850209716Sjeff      bsi_from = bsi_last (middle_bb);
851209716Sjeff      bsi_move_before (&bsi_from, &bsi);
852209716Sjeff    }
853209716Sjeff
854209716Sjeff  /* Emit the statement to compute min/max.  */
855209716Sjeff  result = duplicate_ssa_name (PHI_RESULT (phi), NULL);
856207141Sjeff  new = build2 (MODIFY_EXPR, type, result,
857207141Sjeff		build2 (minmax, type, arg0, arg1));
858207141Sjeff  SSA_NAME_DEF_STMT (result) = new;
859207141Sjeff  bsi = bsi_last (cond_bb);
860207141Sjeff  bsi_insert_before (&bsi, new, BSI_NEW_STMT);
861207141Sjeff
862207141Sjeff  replace_phi_edge_with_variable (cond_bb, e1, phi, result);
863207141Sjeff  return true;
864207141Sjeff}
865207141Sjeff
866207141Sjeff/*  The function absolute_replacement does the main work of doing the absolute
867207141Sjeff    replacement.  Return true if the replacement is done.  Otherwise return
868207141Sjeff    false.
869207141Sjeff    bb is the basic block where the replacement is going to be done on.  arg0
870207141Sjeff    is argument 0 from the phi.  Likewise for arg1.  */
871207141Sjeff
872207141Sjeffstatic bool
873207141Sjeffabs_replacement (basic_block cond_bb, basic_block middle_bb,
874207141Sjeff		 edge e0 ATTRIBUTE_UNUSED, edge e1,
875207141Sjeff		 tree phi, tree arg0, tree arg1)
876207141Sjeff{
877207141Sjeff  tree result;
878207141Sjeff  tree new, cond;
879207141Sjeff  block_stmt_iterator bsi;
880207141Sjeff  edge true_edge, false_edge;
881207141Sjeff  tree assign;
882207141Sjeff  edge e;
883207141Sjeff  tree rhs, lhs;
884207141Sjeff  bool negate;
885207141Sjeff  enum tree_code cond_code;
886207141Sjeff
887207141Sjeff  /* If the type says honor signed zeros we cannot do this
888207141Sjeff     optimization.  */
889207141Sjeff  if (HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
890207141Sjeff    return false;
891207141Sjeff
892207141Sjeff  /* OTHER_BLOCK must have only one executable statement which must have the
893207141Sjeff     form arg0 = -arg1 or arg1 = -arg0.  */
894207141Sjeff
895207141Sjeff  assign = last_and_only_stmt (middle_bb);
896207141Sjeff  /* If we did not find the proper negation assignment, then we can not
897207141Sjeff     optimize.  */
898207141Sjeff  if (assign == NULL)
899207141Sjeff    return false;
900207141Sjeff
901207141Sjeff  /* If we got here, then we have found the only executable statement
902207141Sjeff     in OTHER_BLOCK.  If it is anything other than arg = -arg1 or
903207141Sjeff     arg1 = -arg0, then we can not optimize.  */
904207141Sjeff  if (TREE_CODE (assign) != MODIFY_EXPR)
905207141Sjeff    return false;
906207141Sjeff
907207141Sjeff  lhs = TREE_OPERAND (assign, 0);
908207141Sjeff  rhs = TREE_OPERAND (assign, 1);
909207141Sjeff
910207141Sjeff  if (TREE_CODE (rhs) != NEGATE_EXPR)
911207141Sjeff    return false;
912207141Sjeff
913207141Sjeff  rhs = TREE_OPERAND (rhs, 0);
914207141Sjeff
915207141Sjeff  /* The assignment has to be arg0 = -arg1 or arg1 = -arg0.  */
916207141Sjeff  if (!(lhs == arg0 && rhs == arg1)
917207141Sjeff      && !(lhs == arg1 && rhs == arg0))
918207141Sjeff    return false;
919207141Sjeff
920207141Sjeff  cond = COND_EXPR_COND (last_stmt (cond_bb));
921209408Sdelphij  result = PHI_RESULT (phi);
922207141Sjeff
923207141Sjeff  /* Only relationals comparing arg[01] against zero are interesting.  */
924207141Sjeff  cond_code = TREE_CODE (cond);
925207141Sjeff  if (cond_code != GT_EXPR && cond_code != GE_EXPR
926207141Sjeff      && cond_code != LT_EXPR && cond_code != LE_EXPR)
927207141Sjeff    return false;
928207141Sjeff
929207141Sjeff  /* Make sure the conditional is arg[01] OP y.  */
930207141Sjeff  if (TREE_OPERAND (cond, 0) != rhs)
931207141Sjeff    return false;
932207141Sjeff
933207141Sjeff  if (FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (cond, 1)))
934207141Sjeff	       ? real_zerop (TREE_OPERAND (cond, 1))
935207141Sjeff	       : integer_zerop (TREE_OPERAND (cond, 1)))
936207141Sjeff    ;
937207141Sjeff  else
938207141Sjeff    return false;
939207141Sjeff
940207141Sjeff  /* We need to know which is the true edge and which is the false
941207141Sjeff     edge so that we know if have abs or negative abs.  */
942207141Sjeff  extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge);
943207141Sjeff
944207141Sjeff  /* For GT_EXPR/GE_EXPR, if the true edge goes to OTHER_BLOCK, then we
945207141Sjeff     will need to negate the result.  Similarly for LT_EXPR/LE_EXPR if
946207141Sjeff     the false edge goes to OTHER_BLOCK.  */
947207141Sjeff  if (cond_code == GT_EXPR || cond_code == GE_EXPR)
948207141Sjeff    e = true_edge;
949207141Sjeff  else
950207141Sjeff    e = false_edge;
951207141Sjeff
952207141Sjeff  if (e->dest == middle_bb)
953207141Sjeff    negate = true;
954207141Sjeff  else
955207141Sjeff    negate = false;
956207141Sjeff
957207141Sjeff  result = duplicate_ssa_name (result, NULL);
958207141Sjeff
959207141Sjeff  if (negate)
960207141Sjeff    {
961207141Sjeff      tree tmp = create_tmp_var (TREE_TYPE (result), NULL);
962207141Sjeff      add_referenced_var (tmp);
963207141Sjeff      lhs = make_ssa_name (tmp, NULL);
964207141Sjeff    }
965207141Sjeff  else
966207141Sjeff    lhs = result;
967207141Sjeff
968207141Sjeff  /* Build the modify expression with abs expression.  */
969207141Sjeff  new = build2 (MODIFY_EXPR, TREE_TYPE (lhs),
970207141Sjeff		lhs, build1 (ABS_EXPR, TREE_TYPE (lhs), rhs));
971207141Sjeff  SSA_NAME_DEF_STMT (lhs) = new;
972207141Sjeff
973207141Sjeff  bsi = bsi_last (cond_bb);
974207141Sjeff  bsi_insert_before (&bsi, new, BSI_NEW_STMT);
975207141Sjeff
976207141Sjeff  if (negate)
977209408Sdelphij    {
978207141Sjeff      /* Get the right BSI.  We want to insert after the recently
979207141Sjeff	 added ABS_EXPR statement (which we know is the first statement
980207141Sjeff	 in the block.  */
981207141Sjeff      new = build2 (MODIFY_EXPR, TREE_TYPE (result),
982207141Sjeff		    result, build1 (NEGATE_EXPR, TREE_TYPE (lhs), lhs));
983207141Sjeff      SSA_NAME_DEF_STMT (result) = new;
984207141Sjeff
985207141Sjeff      bsi_insert_after (&bsi, new, BSI_NEW_STMT);
986207141Sjeff    }
987207141Sjeff
988207141Sjeff  replace_phi_edge_with_variable (cond_bb, e1, phi, result);
989207141Sjeff
990207141Sjeff  /* Note that we optimized this PHI.  */
991207141Sjeff  return true;
992207141Sjeff}
993207141Sjeff
994207141Sjeff
995207141Sjeff/* Always do these optimizations if we have SSA
996207141Sjeff   trees to work on.  */
997207141Sjeffstatic bool
998207141Sjeffgate_phiopt (void)
999207141Sjeff{
1000207141Sjeff  return 1;
1001207141Sjeff}
1002207141Sjeff
1003207141Sjeffstruct tree_opt_pass pass_phiopt =
1004207141Sjeff{
1005207141Sjeff  "phiopt",				/* name */
1006207141Sjeff  gate_phiopt,				/* gate */
1007207141Sjeff  tree_ssa_phiopt,			/* execute */
1008207141Sjeff  NULL,					/* sub */
1009207141Sjeff  NULL,					/* next */
1010207141Sjeff  0,					/* static_pass_number */
1011207141Sjeff  TV_TREE_PHIOPT,			/* tv_id */
1012207141Sjeff  PROP_cfg | PROP_ssa | PROP_alias,	/* properties_required */
1013207141Sjeff  0,					/* properties_provided */
1014207141Sjeff  0,					/* properties_destroyed */
1015207141Sjeff  0,					/* todo_flags_start */
1016207141Sjeff  TODO_dump_func
1017207141Sjeff    | TODO_ggc_collect
1018207141Sjeff    | TODO_verify_ssa
1019207141Sjeff    | TODO_verify_flow
1020207141Sjeff    | TODO_verify_stmts,		/* todo_flags_finish */
1021207141Sjeff  0					/* letter */
1022207141Sjeff};
1023207141Sjeff