00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "config.h"
00022 #include "system.h"
00023 #include "coretypes.h"
00024 #include "tm.h"
00025 #include "ggc.h"
00026 #include "tree.h"
00027 #include "rtl.h"
00028 #include "flags.h"
00029 #include "tm_p.h"
00030 #include "basic-block.h"
00031 #include "timevar.h"
00032 #include "diagnostic.h"
00033 #include "tree-flow.h"
00034 #include "tree-pass.h"
00035 #include "tree-dump.h"
00036 #include "langhooks.h"
00037
00038 static unsigned int tree_ssa_phiopt (void);
00039 static bool conditional_replacement (basic_block, basic_block,
00040 edge, edge, tree, tree, tree);
00041 static bool value_replacement (basic_block, basic_block,
00042 edge, edge, tree, tree, tree);
00043 static bool minmax_replacement (basic_block, basic_block,
00044 edge, edge, tree, tree, tree);
00045 static bool abs_replacement (basic_block, basic_block,
00046 edge, edge, tree, tree, tree);
00047 static void replace_phi_edge_with_variable (basic_block, edge, tree, tree);
00048 static basic_block *blocks_in_phiopt_order (void);
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 static unsigned int
00137 tree_ssa_phiopt (void)
00138 {
00139 basic_block bb;
00140 basic_block *bb_order;
00141 unsigned n, i;
00142 bool cfgchanged = false;
00143
00144
00145
00146
00147
00148
00149
00150
00151 bb_order = blocks_in_phiopt_order ();
00152 n = n_basic_blocks - NUM_FIXED_BLOCKS;
00153
00154 for (i = 0; i < n; i++)
00155 {
00156 tree cond_expr;
00157 tree phi;
00158 basic_block bb1, bb2;
00159 edge e1, e2;
00160 tree arg0, arg1;
00161
00162 bb = bb_order[i];
00163
00164 cond_expr = last_stmt (bb);
00165
00166 if (!cond_expr
00167 || TREE_CODE (cond_expr) != COND_EXPR)
00168 continue;
00169
00170 e1 = EDGE_SUCC (bb, 0);
00171 bb1 = e1->dest;
00172 e2 = EDGE_SUCC (bb, 1);
00173 bb2 = e2->dest;
00174
00175
00176 if ((e1->flags & EDGE_ABNORMAL) != 0
00177 || (e2->flags & EDGE_ABNORMAL) != 0)
00178 continue;
00179
00180
00181 if (EDGE_COUNT (bb1->succs) == 0
00182 || bb2 == NULL
00183 || EDGE_COUNT (bb2->succs) == 0)
00184 continue;
00185
00186
00187 if (EDGE_SUCC (bb1, 0)->dest == bb2)
00188 ;
00189 else if (EDGE_SUCC (bb2, 0)->dest == bb1)
00190 {
00191 basic_block bb_tmp = bb1;
00192 edge e_tmp = e1;
00193 bb1 = bb2;
00194 bb2 = bb_tmp;
00195 e1 = e2;
00196 e2 = e_tmp;
00197 }
00198 else
00199 continue;
00200
00201 e1 = EDGE_SUCC (bb1, 0);
00202
00203
00204 if (!single_succ_p (bb1)
00205 || (e1->flags & EDGE_FALLTHRU) == 0)
00206 continue;
00207
00208
00209
00210 if (!single_pred_p (bb1)
00211 || single_pred (bb1) != bb)
00212 continue;
00213
00214 phi = phi_nodes (bb2);
00215
00216
00217
00218
00219 if (!phi || PHI_CHAIN (phi) != NULL)
00220 continue;
00221
00222 arg0 = PHI_ARG_DEF_TREE (phi, e1->dest_idx);
00223 arg1 = PHI_ARG_DEF_TREE (phi, e2->dest_idx);
00224
00225
00226
00227 gcc_assert (arg0 != NULL && arg1 != NULL);
00228
00229
00230 if (conditional_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
00231 cfgchanged = true;
00232 else if (value_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
00233 cfgchanged = true;
00234 else if (abs_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
00235 cfgchanged = true;
00236 else if (minmax_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
00237 cfgchanged = true;
00238 }
00239
00240 free (bb_order);
00241
00242
00243 return cfgchanged ? TODO_cleanup_cfg : 0;
00244 }
00245
00246
00247
00248
00249
00250 static basic_block *
00251 blocks_in_phiopt_order (void)
00252 {
00253 basic_block x, y;
00254 basic_block *order = XNEWVEC (basic_block, n_basic_blocks);
00255 unsigned n = n_basic_blocks - NUM_FIXED_BLOCKS;
00256 unsigned np, i;
00257 sbitmap visited = sbitmap_alloc (last_basic_block);
00258
00259 #define MARK_VISITED(BB) (SET_BIT (visited, (BB)->index))
00260 #define VISITED_P(BB) (TEST_BIT (visited, (BB)->index))
00261
00262 sbitmap_zero (visited);
00263
00264 MARK_VISITED (ENTRY_BLOCK_PTR);
00265 FOR_EACH_BB (x)
00266 {
00267 if (VISITED_P (x))
00268 continue;
00269
00270
00271
00272
00273 for (y = x, np = 1;
00274 single_pred_p (y) && !VISITED_P (single_pred (y));
00275 y = single_pred (y))
00276 np++;
00277 for (y = x, i = n - np;
00278 single_pred_p (y) && !VISITED_P (single_pred (y));
00279 y = single_pred (y), i++)
00280 {
00281 order[i] = y;
00282 MARK_VISITED (y);
00283 }
00284 order[i] = y;
00285 MARK_VISITED (y);
00286
00287 gcc_assert (i == n - 1);
00288 n -= np;
00289 }
00290
00291 sbitmap_free (visited);
00292 gcc_assert (n == 0);
00293 return order;
00294
00295 #undef MARK_VISITED
00296 #undef VISITED_P
00297 }
00298
00299
00300
00301 bool
00302 empty_block_p (basic_block bb)
00303 {
00304 block_stmt_iterator bsi;
00305
00306
00307 bsi = bsi_start (bb);
00308 while (!bsi_end_p (bsi)
00309 && (TREE_CODE (bsi_stmt (bsi)) == LABEL_EXPR
00310 || IS_EMPTY_STMT (bsi_stmt (bsi))))
00311 bsi_next (&bsi);
00312
00313 if (!bsi_end_p (bsi))
00314 return false;
00315
00316 return true;
00317 }
00318
00319
00320
00321
00322
00323 static void
00324 replace_phi_edge_with_variable (basic_block cond_block,
00325 edge e, tree phi, tree new)
00326 {
00327 basic_block bb = bb_for_stmt (phi);
00328 basic_block block_to_remove;
00329 block_stmt_iterator bsi;
00330
00331
00332 SET_USE (PHI_ARG_DEF_PTR (phi, e->dest_idx), new);
00333
00334
00335 if (EDGE_SUCC (cond_block, 0)->dest == bb)
00336 {
00337 EDGE_SUCC (cond_block, 0)->flags |= EDGE_FALLTHRU;
00338 EDGE_SUCC (cond_block, 0)->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
00339 EDGE_SUCC (cond_block, 0)->probability = REG_BR_PROB_BASE;
00340 EDGE_SUCC (cond_block, 0)->count += EDGE_SUCC (cond_block, 1)->count;
00341
00342 block_to_remove = EDGE_SUCC (cond_block, 1)->dest;
00343 }
00344 else
00345 {
00346 EDGE_SUCC (cond_block, 1)->flags |= EDGE_FALLTHRU;
00347 EDGE_SUCC (cond_block, 1)->flags
00348 &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
00349 EDGE_SUCC (cond_block, 1)->probability = REG_BR_PROB_BASE;
00350 EDGE_SUCC (cond_block, 1)->count += EDGE_SUCC (cond_block, 0)->count;
00351
00352 block_to_remove = EDGE_SUCC (cond_block, 0)->dest;
00353 }
00354 delete_basic_block (block_to_remove);
00355
00356
00357 bsi = bsi_last (cond_block);
00358 bsi_remove (&bsi, true);
00359
00360 if (dump_file && (dump_flags & TDF_DETAILS))
00361 fprintf (dump_file,
00362 "COND_EXPR in block %d and PHI in block %d converted to straightline code.\n",
00363 cond_block->index,
00364 bb->index);
00365 }
00366
00367
00368
00369
00370
00371
00372
00373 static bool
00374 conditional_replacement (basic_block cond_bb, basic_block middle_bb,
00375 edge e0, edge e1, tree phi,
00376 tree arg0, tree arg1)
00377 {
00378 tree result;
00379 tree old_result = NULL;
00380 tree new, cond;
00381 block_stmt_iterator bsi;
00382 edge true_edge, false_edge;
00383 tree new_var = NULL;
00384 tree new_var1;
00385
00386
00387
00388 if ((integer_zerop (arg0) && integer_onep (arg1))
00389 || (integer_zerop (arg1) && integer_onep (arg0)))
00390 ;
00391 else
00392 return false;
00393
00394 if (!empty_block_p (middle_bb))
00395 return false;
00396
00397
00398
00399
00400
00401
00402 cond = COND_EXPR_COND (last_stmt (cond_bb));
00403 result = PHI_RESULT (phi);
00404 if (TREE_CODE (cond) != SSA_NAME
00405 && !lang_hooks.types_compatible_p (TREE_TYPE (cond), TREE_TYPE (result)))
00406 {
00407 tree tmp;
00408
00409 if (!COMPARISON_CLASS_P (cond))
00410 return false;
00411
00412 tmp = create_tmp_var (TREE_TYPE (cond), NULL);
00413 add_referenced_var (tmp);
00414 new_var = make_ssa_name (tmp, NULL);
00415 old_result = cond;
00416 cond = new_var;
00417 }
00418
00419
00420
00421
00422 if (!lang_hooks.types_compatible_p (TREE_TYPE (cond), TREE_TYPE (result)))
00423 cond = fold_convert (TREE_TYPE (result), cond);
00424
00425
00426
00427 extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge);
00428
00429
00430
00431 bsi = bsi_last (cond_bb);
00432 bsi_insert_before (&bsi, build_empty_stmt (), BSI_NEW_STMT);
00433
00434 if (old_result)
00435 {
00436 tree new1;
00437
00438 new1 = build2 (TREE_CODE (old_result), TREE_TYPE (old_result),
00439 TREE_OPERAND (old_result, 0),
00440 TREE_OPERAND (old_result, 1));
00441
00442 new1 = build2 (MODIFY_EXPR, TREE_TYPE (old_result), new_var, new1);
00443 SSA_NAME_DEF_STMT (new_var) = new1;
00444
00445 bsi_insert_after (&bsi, new1, BSI_NEW_STMT);
00446 }
00447
00448 new_var1 = duplicate_ssa_name (PHI_RESULT (phi), NULL);
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468 if ((e0 == true_edge && integer_onep (arg0))
00469 || (e0 == false_edge && integer_zerop (arg0))
00470 || (e1 == true_edge && integer_onep (arg1))
00471 || (e1 == false_edge && integer_zerop (arg1)))
00472 {
00473 new = build2 (MODIFY_EXPR, TREE_TYPE (new_var1), new_var1, cond);
00474 }
00475 else
00476 {
00477 tree cond1 = invert_truthvalue (cond);
00478
00479 cond = cond1;
00480
00481
00482
00483 if (TREE_CODE (cond) == COND_EXPR)
00484 {
00485 release_ssa_name (new_var1);
00486 return false;
00487 }
00488
00489
00490
00491 if (is_gimple_cast (cond))
00492 cond1 = TREE_OPERAND (cond, 0);
00493 if (TREE_CODE (cond1) == TRUTH_NOT_EXPR
00494 && !is_gimple_val (TREE_OPERAND (cond1, 0)))
00495 {
00496 release_ssa_name (new_var1);
00497 return false;
00498 }
00499
00500
00501
00502 if (is_gimple_cast (cond)
00503 && !is_gimple_val (TREE_OPERAND (cond, 0)))
00504 {
00505 tree op0, tmp, cond_tmp;
00506
00507
00508
00509
00510 gcc_assert (TREE_CODE (cond) == NOP_EXPR
00511 || TREE_CODE (cond) == CONVERT_EXPR);
00512
00513 op0 = TREE_OPERAND (cond, 0);
00514 tmp = create_tmp_var (TREE_TYPE (op0), NULL);
00515 add_referenced_var (tmp);
00516 cond_tmp = make_ssa_name (tmp, NULL);
00517 new = build2 (MODIFY_EXPR, TREE_TYPE (cond_tmp), cond_tmp, op0);
00518 SSA_NAME_DEF_STMT (cond_tmp) = new;
00519
00520 bsi_insert_after (&bsi, new, BSI_NEW_STMT);
00521 cond = fold_convert (TREE_TYPE (result), cond_tmp);
00522 }
00523
00524 new = build2 (MODIFY_EXPR, TREE_TYPE (new_var1), new_var1, cond);
00525 }
00526
00527 bsi_insert_after (&bsi, new, BSI_NEW_STMT);
00528
00529 SSA_NAME_DEF_STMT (new_var1) = new;
00530
00531 replace_phi_edge_with_variable (cond_bb, e1, phi, new_var1);
00532
00533
00534 return true;
00535 }
00536
00537
00538
00539
00540
00541
00542
00543 static bool
00544 value_replacement (basic_block cond_bb, basic_block middle_bb,
00545 edge e0, edge e1, tree phi,
00546 tree arg0, tree arg1)
00547 {
00548 tree cond;
00549 edge true_edge, false_edge;
00550
00551
00552
00553 if (HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
00554 return false;
00555
00556 if (!empty_block_p (middle_bb))
00557 return false;
00558
00559 cond = COND_EXPR_COND (last_stmt (cond_bb));
00560
00561
00562 if (TREE_CODE (cond) != NE_EXPR && TREE_CODE (cond) != EQ_EXPR)
00563 return false;
00564
00565
00566
00567 extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge);
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580 if ((operand_equal_for_phi_arg_p (arg0, TREE_OPERAND (cond, 0))
00581 && operand_equal_for_phi_arg_p (arg1, TREE_OPERAND (cond, 1)))
00582 || (operand_equal_for_phi_arg_p (arg1, TREE_OPERAND (cond, 0))
00583 && operand_equal_for_phi_arg_p (arg0, TREE_OPERAND (cond, 1))))
00584 {
00585 edge e;
00586 tree arg;
00587
00588
00589
00590
00591 e = (TREE_CODE (cond) == NE_EXPR ? true_edge : false_edge);
00592
00593
00594
00595
00596
00597 if (e->dest == middle_bb)
00598 e = single_succ_edge (e->dest);
00599
00600
00601
00602 if (e0 == e)
00603 arg = arg0;
00604 else
00605 arg = arg1;
00606
00607 replace_phi_edge_with_variable (cond_bb, e1, phi, arg);
00608
00609
00610 return true;
00611 }
00612 return false;
00613 }
00614
00615
00616
00617
00618
00619
00620
00621 static bool
00622 minmax_replacement (basic_block cond_bb, basic_block middle_bb,
00623 edge e0, edge e1, tree phi,
00624 tree arg0, tree arg1)
00625 {
00626 tree result, type;
00627 tree cond, new;
00628 edge true_edge, false_edge;
00629 enum tree_code cmp, minmax, ass_code;
00630 tree smaller, larger, arg_true, arg_false;
00631 block_stmt_iterator bsi, bsi_from;
00632
00633 type = TREE_TYPE (PHI_RESULT (phi));
00634
00635
00636 if (HONOR_NANS (TYPE_MODE (type)))
00637 return false;
00638
00639 cond = COND_EXPR_COND (last_stmt (cond_bb));
00640 cmp = TREE_CODE (cond);
00641 result = PHI_RESULT (phi);
00642
00643
00644
00645 if (cmp == LT_EXPR || cmp == LE_EXPR)
00646 {
00647 smaller = TREE_OPERAND (cond, 0);
00648 larger = TREE_OPERAND (cond, 1);
00649 }
00650 else if (cmp == GT_EXPR || cmp == GE_EXPR)
00651 {
00652 smaller = TREE_OPERAND (cond, 1);
00653 larger = TREE_OPERAND (cond, 0);
00654 }
00655 else
00656 return false;
00657
00658
00659
00660 extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge);
00661
00662
00663 if (true_edge->dest == middle_bb)
00664 true_edge = EDGE_SUCC (true_edge->dest, 0);
00665 if (false_edge->dest == middle_bb)
00666 false_edge = EDGE_SUCC (false_edge->dest, 0);
00667
00668 if (true_edge == e0)
00669 {
00670 gcc_assert (false_edge == e1);
00671 arg_true = arg0;
00672 arg_false = arg1;
00673 }
00674 else
00675 {
00676 gcc_assert (false_edge == e0);
00677 gcc_assert (true_edge == e1);
00678 arg_true = arg1;
00679 arg_false = arg0;
00680 }
00681
00682 if (empty_block_p (middle_bb))
00683 {
00684 if (operand_equal_for_phi_arg_p (arg_true, smaller)
00685 && operand_equal_for_phi_arg_p (arg_false, larger))
00686 {
00687
00688
00689
00690
00691
00692
00693 minmax = MIN_EXPR;
00694 }
00695 else if (operand_equal_for_phi_arg_p (arg_false, smaller)
00696 && operand_equal_for_phi_arg_p (arg_true, larger))
00697 minmax = MAX_EXPR;
00698 else
00699 return false;
00700 }
00701 else
00702 {
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714 tree assign = last_and_only_stmt (middle_bb);
00715 tree lhs, rhs, op0, op1, bound;
00716
00717 if (!assign
00718 || TREE_CODE (assign) != MODIFY_EXPR)
00719 return false;
00720
00721 lhs = TREE_OPERAND (assign, 0);
00722 rhs = TREE_OPERAND (assign, 1);
00723 ass_code = TREE_CODE (rhs);
00724 if (ass_code != MAX_EXPR && ass_code != MIN_EXPR)
00725 return false;
00726 op0 = TREE_OPERAND (rhs, 0);
00727 op1 = TREE_OPERAND (rhs, 1);
00728
00729 if (true_edge->src == middle_bb)
00730 {
00731
00732 if (!operand_equal_for_phi_arg_p (lhs, arg_true))
00733 return false;
00734
00735 if (operand_equal_for_phi_arg_p (arg_false, larger))
00736 {
00737
00738
00739
00740
00741
00742
00743
00744 if (ass_code != MAX_EXPR)
00745 return false;
00746
00747 minmax = MIN_EXPR;
00748 if (operand_equal_for_phi_arg_p (op0, smaller))
00749 bound = op1;
00750 else if (operand_equal_for_phi_arg_p (op1, smaller))
00751 bound = op0;
00752 else
00753 return false;
00754
00755
00756 if (!integer_nonzerop (fold_build2 (LE_EXPR, boolean_type_node,
00757 bound, larger)))
00758 return false;
00759 }
00760 else if (operand_equal_for_phi_arg_p (arg_false, smaller))
00761 {
00762
00763
00764
00765
00766
00767
00768
00769 if (ass_code != MIN_EXPR)
00770 return false;
00771
00772 minmax = MAX_EXPR;
00773 if (operand_equal_for_phi_arg_p (op0, larger))
00774 bound = op1;
00775 else if (operand_equal_for_phi_arg_p (op1, larger))
00776 bound = op0;
00777 else
00778 return false;
00779
00780
00781 if (!integer_nonzerop (fold_build2 (GE_EXPR, boolean_type_node,
00782 bound, smaller)))
00783 return false;
00784 }
00785 else
00786 return false;
00787 }
00788 else
00789 {
00790
00791 if (!operand_equal_for_phi_arg_p (lhs, arg_false))
00792 return false;
00793
00794 if (operand_equal_for_phi_arg_p (arg_true, larger))
00795 {
00796
00797
00798
00799
00800
00801
00802
00803 if (ass_code != MIN_EXPR)
00804 return false;
00805
00806 minmax = MAX_EXPR;
00807 if (operand_equal_for_phi_arg_p (op0, smaller))
00808 bound = op1;
00809 else if (operand_equal_for_phi_arg_p (op1, smaller))
00810 bound = op0;
00811 else
00812 return false;
00813
00814
00815 if (!integer_nonzerop (fold_build2 (GE_EXPR, boolean_type_node,
00816 bound, larger)))
00817 return false;
00818 }
00819 else if (operand_equal_for_phi_arg_p (arg_true, smaller))
00820 {
00821
00822
00823
00824
00825
00826
00827
00828 if (ass_code != MAX_EXPR)
00829 return false;
00830
00831 minmax = MIN_EXPR;
00832 if (operand_equal_for_phi_arg_p (op0, larger))
00833 bound = op1;
00834 else if (operand_equal_for_phi_arg_p (op1, larger))
00835 bound = op0;
00836 else
00837 return false;
00838
00839
00840 if (!integer_nonzerop (fold_build2 (LE_EXPR, boolean_type_node,
00841 bound, smaller)))
00842 return false;
00843 }
00844 else
00845 return false;
00846 }
00847
00848
00849 bsi = bsi_last (cond_bb);
00850 bsi_from = bsi_last (middle_bb);
00851 bsi_move_before (&bsi_from, &bsi);
00852 }
00853
00854
00855 result = duplicate_ssa_name (PHI_RESULT (phi), NULL);
00856 new = build2 (MODIFY_EXPR, type, result,
00857 build2 (minmax, type, arg0, arg1));
00858 SSA_NAME_DEF_STMT (result) = new;
00859 bsi = bsi_last (cond_bb);
00860 bsi_insert_before (&bsi, new, BSI_NEW_STMT);
00861
00862 replace_phi_edge_with_variable (cond_bb, e1, phi, result);
00863 return true;
00864 }
00865
00866
00867
00868
00869
00870
00871
00872 static bool
00873 abs_replacement (basic_block cond_bb, basic_block middle_bb,
00874 edge e0 ATTRIBUTE_UNUSED, edge e1,
00875 tree phi, tree arg0, tree arg1)
00876 {
00877 tree result;
00878 tree new, cond;
00879 block_stmt_iterator bsi;
00880 edge true_edge, false_edge;
00881 tree assign;
00882 edge e;
00883 tree rhs, lhs;
00884 bool negate;
00885 enum tree_code cond_code;
00886
00887
00888
00889 if (HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
00890 return false;
00891
00892
00893
00894
00895 assign = last_and_only_stmt (middle_bb);
00896
00897
00898 if (assign == NULL)
00899 return false;
00900
00901
00902
00903
00904 if (TREE_CODE (assign) != MODIFY_EXPR)
00905 return false;
00906
00907 lhs = TREE_OPERAND (assign, 0);
00908 rhs = TREE_OPERAND (assign, 1);
00909
00910 if (TREE_CODE (rhs) != NEGATE_EXPR)
00911 return false;
00912
00913 rhs = TREE_OPERAND (rhs, 0);
00914
00915
00916 if (!(lhs == arg0 && rhs == arg1)
00917 && !(lhs == arg1 && rhs == arg0))
00918 return false;
00919
00920 cond = COND_EXPR_COND (last_stmt (cond_bb));
00921 result = PHI_RESULT (phi);
00922
00923
00924 cond_code = TREE_CODE (cond);
00925 if (cond_code != GT_EXPR && cond_code != GE_EXPR
00926 && cond_code != LT_EXPR && cond_code != LE_EXPR)
00927 return false;
00928
00929
00930 if (TREE_OPERAND (cond, 0) != rhs)
00931 return false;
00932
00933 if (FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (cond, 1)))
00934 ? real_zerop (TREE_OPERAND (cond, 1))
00935 : integer_zerop (TREE_OPERAND (cond, 1)))
00936 ;
00937 else
00938 return false;
00939
00940
00941
00942 extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge);
00943
00944
00945
00946
00947 if (cond_code == GT_EXPR || cond_code == GE_EXPR)
00948 e = true_edge;
00949 else
00950 e = false_edge;
00951
00952 if (e->dest == middle_bb)
00953 negate = true;
00954 else
00955 negate = false;
00956
00957 result = duplicate_ssa_name (result, NULL);
00958
00959 if (negate)
00960 {
00961 tree tmp = create_tmp_var (TREE_TYPE (result), NULL);
00962 add_referenced_var (tmp);
00963 lhs = make_ssa_name (tmp, NULL);
00964 }
00965 else
00966 lhs = result;
00967
00968
00969 new = build2 (MODIFY_EXPR, TREE_TYPE (lhs),
00970 lhs, build1 (ABS_EXPR, TREE_TYPE (lhs), rhs));
00971 SSA_NAME_DEF_STMT (lhs) = new;
00972
00973 bsi = bsi_last (cond_bb);
00974 bsi_insert_before (&bsi, new, BSI_NEW_STMT);
00975
00976 if (negate)
00977 {
00978
00979
00980
00981 new = build2 (MODIFY_EXPR, TREE_TYPE (result),
00982 result, build1 (NEGATE_EXPR, TREE_TYPE (lhs), lhs));
00983 SSA_NAME_DEF_STMT (result) = new;
00984
00985 bsi_insert_after (&bsi, new, BSI_NEW_STMT);
00986 }
00987
00988 replace_phi_edge_with_variable (cond_bb, e1, phi, result);
00989
00990
00991 return true;
00992 }
00993
00994
00995
00996
00997 static bool
00998 gate_phiopt (void)
00999 {
01000 return 1;
01001 }
01002
01003 struct tree_opt_pass pass_phiopt =
01004 {
01005 "phiopt",
01006 gate_phiopt,
01007 tree_ssa_phiopt,
01008 NULL,
01009 NULL,
01010 0,
01011 TV_TREE_PHIOPT,
01012 PROP_cfg | PROP_ssa | PROP_alias,
01013 0,
01014 0,
01015 0,
01016 TODO_dump_func
01017 | TODO_ggc_collect
01018 | TODO_verify_ssa
01019 | TODO_verify_flow
01020 | TODO_verify_stmts,
01021 0
01022 };