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