00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "config.h"
00023 #include "system.h"
00024 #include "coretypes.h"
00025 #include "tm.h"
00026 #include "errors.h"
00027 #include "ggc.h"
00028 #include "tree.h"
00029 #include "basic-block.h"
00030 #include "diagnostic.h"
00031 #include "tree-inline.h"
00032 #include "tree-flow.h"
00033 #include "tree-gimple.h"
00034 #include "tree-dump.h"
00035 #include "timevar.h"
00036 #include "tree-iterator.h"
00037 #include "tree-pass.h"
00038 #include "alloc-pool.h"
00039 #include "vec.h"
00040 #include "langhooks.h"
00041
00042
00043
00044
00045
00046
00047
00048
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
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 static struct
00162 {
00163 int linearized;
00164 int constants_eliminated;
00165 int ops_eliminated;
00166 int rewritten;
00167 } reassociate_stats;
00168
00169
00170 typedef struct operand_entry
00171 {
00172 unsigned int rank;
00173 tree op;
00174 } *operand_entry_t;
00175
00176 static alloc_pool operand_entry_pool;
00177
00178
00179
00180
00181
00182 static unsigned int *bb_rank;
00183
00184
00185 static htab_t operand_rank;
00186
00187
00188
00189
00190 static operand_entry_t
00191 find_operand_rank (tree e)
00192 {
00193 void **slot;
00194 struct operand_entry vrd;
00195
00196 vrd.op = e;
00197 slot = htab_find_slot (operand_rank, &vrd, NO_INSERT);
00198 if (!slot)
00199 return NULL;
00200 return ((operand_entry_t) *slot);
00201 }
00202
00203
00204
00205 static void
00206 insert_operand_rank (tree e, unsigned int rank)
00207 {
00208 void **slot;
00209 operand_entry_t new_pair = pool_alloc (operand_entry_pool);
00210
00211 new_pair->op = e;
00212 new_pair->rank = rank;
00213 slot = htab_find_slot (operand_rank, new_pair, INSERT);
00214 gcc_assert (*slot == NULL);
00215 *slot = new_pair;
00216 }
00217
00218
00219
00220 static hashval_t
00221 operand_entry_hash (const void *p)
00222 {
00223 const operand_entry_t vr = (operand_entry_t) p;
00224 return iterative_hash_expr (vr->op, 0);
00225 }
00226
00227
00228
00229 static int
00230 operand_entry_eq (const void *p1, const void *p2)
00231 {
00232 const operand_entry_t vr1 = (operand_entry_t) p1;
00233 const operand_entry_t vr2 = (operand_entry_t) p2;
00234 return vr1->op == vr2->op;
00235 }
00236
00237
00238
00239 static unsigned int
00240 get_rank (tree e)
00241 {
00242 operand_entry_t vr;
00243
00244
00245 if (is_gimple_min_invariant (e))
00246 return 0;
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 if (TREE_CODE (e) == SSA_NAME)
00260 {
00261 tree stmt;
00262 tree rhs;
00263 unsigned int rank, maxrank;
00264 int i;
00265
00266 if (TREE_CODE (SSA_NAME_VAR (e)) == PARM_DECL
00267 && e == default_def (SSA_NAME_VAR (e)))
00268 return find_operand_rank (e)->rank;
00269
00270 stmt = SSA_NAME_DEF_STMT (e);
00271 if (bb_for_stmt (stmt) == NULL)
00272 return 0;
00273
00274 if (TREE_CODE (stmt) != MODIFY_EXPR
00275 || !ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
00276 return bb_rank[bb_for_stmt (stmt)->index];
00277
00278
00279 vr = find_operand_rank (e);
00280 if (vr)
00281 return vr->rank;
00282
00283
00284
00285 rank = 0;
00286 maxrank = bb_rank[bb_for_stmt(stmt)->index];
00287 rhs = TREE_OPERAND (stmt, 1);
00288 if (TREE_CODE_LENGTH (TREE_CODE (rhs)) == 0)
00289 rank = MAX (rank, get_rank (rhs));
00290 else
00291 {
00292 for (i = 0;
00293 i < TREE_CODE_LENGTH (TREE_CODE (rhs))
00294 && TREE_OPERAND (rhs, i)
00295 && rank != maxrank;
00296 i++)
00297 rank = MAX(rank, get_rank (TREE_OPERAND (rhs, i)));
00298 }
00299
00300 if (dump_file && (dump_flags & TDF_DETAILS))
00301 {
00302 fprintf (dump_file, "Rank for ");
00303 print_generic_expr (dump_file, e, 0);
00304 fprintf (dump_file, " is %d\n", (rank + 1));
00305 }
00306
00307
00308 insert_operand_rank (e, (rank + 1));
00309 return (rank + 1);
00310 }
00311
00312
00313 return 0;
00314 }
00315
00316 DEF_VEC_P(operand_entry_t);
00317 DEF_VEC_ALLOC_P(operand_entry_t, heap);
00318
00319
00320
00321 #define INTEGER_CONST_TYPE 1 << 3
00322 #define FLOAT_CONST_TYPE 1 << 2
00323 #define OTHER_CONST_TYPE 1 << 1
00324
00325
00326
00327 static inline int
00328 constant_type (tree t)
00329 {
00330 if (INTEGRAL_TYPE_P (TREE_TYPE (t)))
00331 return INTEGER_CONST_TYPE;
00332 else if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (t)))
00333 return FLOAT_CONST_TYPE;
00334 else
00335 return OTHER_CONST_TYPE;
00336 }
00337
00338
00339
00340 static int
00341 sort_by_operand_rank (const void *pa, const void *pb)
00342 {
00343 const operand_entry_t oea = *(const operand_entry_t *)pa;
00344 const operand_entry_t oeb = *(const operand_entry_t *)pb;
00345
00346
00347
00348
00349 if (oeb->rank == 0 && oea->rank == 0)
00350 return constant_type (oeb->op) - constant_type (oea->op);
00351
00352
00353
00354 if ((oeb->rank - oea->rank == 0)
00355 && TREE_CODE (oea->op) == SSA_NAME
00356 && TREE_CODE (oeb->op) == SSA_NAME)
00357 return SSA_NAME_VERSION (oeb->op) - SSA_NAME_VERSION (oea->op);
00358
00359 return oeb->rank - oea->rank;
00360 }
00361
00362
00363
00364 static void
00365 add_to_ops_vec (VEC(operand_entry_t, heap) **ops, tree op)
00366 {
00367 operand_entry_t oe = pool_alloc (operand_entry_pool);
00368
00369 oe->op = op;
00370 oe->rank = get_rank (op);
00371 VEC_safe_push (operand_entry_t, heap, *ops, oe);
00372 }
00373
00374
00375
00376
00377 static bool
00378 is_reassociable_op (tree stmt, enum tree_code code)
00379 {
00380 if (!IS_EMPTY_STMT (stmt)
00381 && TREE_CODE (stmt) == MODIFY_EXPR
00382 && TREE_CODE (TREE_OPERAND (stmt, 1)) == code
00383 && has_single_use (TREE_OPERAND (stmt, 0)))
00384 return true;
00385 return false;
00386 }
00387
00388
00389
00390
00391
00392 static tree
00393 get_unary_op (tree name, enum tree_code opcode)
00394 {
00395 tree stmt = SSA_NAME_DEF_STMT (name);
00396 tree rhs;
00397
00398 if (TREE_CODE (stmt) != MODIFY_EXPR)
00399 return NULL_TREE;
00400
00401 rhs = TREE_OPERAND (stmt, 1);
00402 if (TREE_CODE (rhs) == opcode)
00403 return TREE_OPERAND (rhs, 0);
00404 return NULL_TREE;
00405 }
00406
00407
00408
00409
00410
00411 static bool
00412 eliminate_duplicate_pair (enum tree_code opcode,
00413 VEC (operand_entry_t, heap) **ops,
00414 bool *all_done,
00415 unsigned int i,
00416 operand_entry_t curr,
00417 operand_entry_t last)
00418 {
00419
00420
00421
00422
00423
00424
00425 if (last && last->op == curr->op)
00426 {
00427 switch (opcode)
00428 {
00429 case MAX_EXPR:
00430 case MIN_EXPR:
00431 case BIT_IOR_EXPR:
00432 case BIT_AND_EXPR:
00433 if (dump_file && (dump_flags & TDF_DETAILS))
00434 {
00435 fprintf (dump_file, "Equivalence: ");
00436 print_generic_expr (dump_file, curr->op, 0);
00437 fprintf (dump_file, " [&|minmax] ");
00438 print_generic_expr (dump_file, last->op, 0);
00439 fprintf (dump_file, " -> ");
00440 print_generic_stmt (dump_file, last->op, 0);
00441 }
00442
00443 VEC_ordered_remove (operand_entry_t, *ops, i);
00444 reassociate_stats.ops_eliminated ++;
00445
00446 return true;
00447
00448 case BIT_XOR_EXPR:
00449 if (dump_file && (dump_flags & TDF_DETAILS))
00450 {
00451 fprintf (dump_file, "Equivalence: ");
00452 print_generic_expr (dump_file, curr->op, 0);
00453 fprintf (dump_file, " ^ ");
00454 print_generic_expr (dump_file, last->op, 0);
00455 fprintf (dump_file, " -> nothing\n");
00456 }
00457
00458 reassociate_stats.ops_eliminated += 2;
00459
00460 if (VEC_length (operand_entry_t, *ops) == 2)
00461 {
00462 VEC_free (operand_entry_t, heap, *ops);
00463 *ops = NULL;
00464 add_to_ops_vec (ops, fold_convert (TREE_TYPE (last->op),
00465 integer_zero_node));
00466 *all_done = true;
00467 }
00468 else
00469 {
00470 VEC_ordered_remove (operand_entry_t, *ops, i-1);
00471 VEC_ordered_remove (operand_entry_t, *ops, i-1);
00472 }
00473
00474 return true;
00475
00476 default:
00477 break;
00478 }
00479 }
00480 return false;
00481 }
00482
00483
00484
00485
00486
00487
00488
00489 static bool
00490 eliminate_plus_minus_pair (enum tree_code opcode,
00491 VEC (operand_entry_t, heap) **ops,
00492 unsigned int currindex,
00493 operand_entry_t curr)
00494 {
00495 tree negateop;
00496 unsigned int i;
00497 operand_entry_t oe;
00498
00499 if (opcode != PLUS_EXPR || TREE_CODE (curr->op) != SSA_NAME)
00500 return false;
00501
00502 negateop = get_unary_op (curr->op, NEGATE_EXPR);
00503 if (negateop == NULL_TREE)
00504 return false;
00505
00506
00507
00508
00509
00510 for (i = currindex + 1;
00511 VEC_iterate (operand_entry_t, *ops, i, oe)
00512 && oe->rank >= curr->rank - 1 ;
00513 i++)
00514 {
00515 if (oe->op == negateop)
00516 {
00517
00518 if (dump_file && (dump_flags & TDF_DETAILS))
00519 {
00520 fprintf (dump_file, "Equivalence: ");
00521 print_generic_expr (dump_file, negateop, 0);
00522 fprintf (dump_file, " + -");
00523 print_generic_expr (dump_file, oe->op, 0);
00524 fprintf (dump_file, " -> 0\n");
00525 }
00526
00527 VEC_ordered_remove (operand_entry_t, *ops, i);
00528 add_to_ops_vec (ops, fold_convert(TREE_TYPE (oe->op),
00529 integer_zero_node));
00530 VEC_ordered_remove (operand_entry_t, *ops, currindex);
00531 reassociate_stats.ops_eliminated ++;
00532
00533 return true;
00534 }
00535 }
00536
00537 return false;
00538 }
00539
00540
00541
00542
00543
00544
00545
00546 static bool
00547 eliminate_not_pairs (enum tree_code opcode,
00548 VEC (operand_entry_t, heap) **ops,
00549 unsigned int currindex,
00550 operand_entry_t curr)
00551 {
00552 tree notop;
00553 unsigned int i;
00554 operand_entry_t oe;
00555
00556 if ((opcode != BIT_IOR_EXPR && opcode != BIT_AND_EXPR)
00557 || TREE_CODE (curr->op) != SSA_NAME)
00558 return false;
00559
00560 notop = get_unary_op (curr->op, BIT_NOT_EXPR);
00561 if (notop == NULL_TREE)
00562 return false;
00563
00564
00565
00566
00567
00568 for (i = currindex + 1;
00569 VEC_iterate (operand_entry_t, *ops, i, oe)
00570 && oe->rank >= curr->rank - 1;
00571 i++)
00572 {
00573 if (oe->op == notop)
00574 {
00575 if (dump_file && (dump_flags & TDF_DETAILS))
00576 {
00577 fprintf (dump_file, "Equivalence: ");
00578 print_generic_expr (dump_file, notop, 0);
00579 if (opcode == BIT_AND_EXPR)
00580 fprintf (dump_file, " & ~");
00581 else if (opcode == BIT_IOR_EXPR)
00582 fprintf (dump_file, " | ~");
00583 print_generic_expr (dump_file, oe->op, 0);
00584 if (opcode == BIT_AND_EXPR)
00585 fprintf (dump_file, " -> 0\n");
00586 else if (opcode == BIT_IOR_EXPR)
00587 fprintf (dump_file, " -> -1\n");
00588 }
00589
00590 if (opcode == BIT_AND_EXPR)
00591 oe->op = fold_convert (TREE_TYPE (oe->op), integer_zero_node);
00592 else if (opcode == BIT_IOR_EXPR)
00593 oe->op = build_low_bits_mask (TREE_TYPE (oe->op),
00594 TYPE_PRECISION (TREE_TYPE (oe->op)));
00595
00596 reassociate_stats.ops_eliminated
00597 += VEC_length (operand_entry_t, *ops) - 1;
00598 VEC_free (operand_entry_t, heap, *ops);
00599 *ops = NULL;
00600 VEC_safe_push (operand_entry_t, heap, *ops, oe);
00601 return true;
00602 }
00603 }
00604
00605 return false;
00606 }
00607
00608
00609
00610
00611
00612
00613
00614
00615 static void
00616 eliminate_using_constants (enum tree_code opcode,
00617 VEC(operand_entry_t, heap) **ops)
00618 {
00619 operand_entry_t oelast = VEC_last (operand_entry_t, *ops);
00620
00621 if (oelast->rank == 0 && INTEGRAL_TYPE_P (TREE_TYPE (oelast->op)))
00622 {
00623 switch (opcode)
00624 {
00625 case BIT_AND_EXPR:
00626 if (integer_zerop (oelast->op))
00627 {
00628 if (VEC_length (operand_entry_t, *ops) != 1)
00629 {
00630 if (dump_file && (dump_flags & TDF_DETAILS))
00631 fprintf (dump_file, "Found & 0, removing all other ops\n");
00632
00633 reassociate_stats.ops_eliminated
00634 += VEC_length (operand_entry_t, *ops) - 1;
00635
00636 VEC_free (operand_entry_t, heap, *ops);
00637 *ops = NULL;
00638 VEC_safe_push (operand_entry_t, heap, *ops, oelast);
00639 return;
00640 }
00641 }
00642 else if (integer_all_onesp (oelast->op))
00643 {
00644 if (VEC_length (operand_entry_t, *ops) != 1)
00645 {
00646 if (dump_file && (dump_flags & TDF_DETAILS))
00647 fprintf (dump_file, "Found & -1, removing\n");
00648 VEC_pop (operand_entry_t, *ops);
00649 reassociate_stats.ops_eliminated++;
00650 }
00651 }
00652 break;
00653 case BIT_IOR_EXPR:
00654 if (integer_all_onesp (oelast->op))
00655 {
00656 if (VEC_length (operand_entry_t, *ops) != 1)
00657 {
00658 if (dump_file && (dump_flags & TDF_DETAILS))
00659 fprintf (dump_file, "Found | -1, removing all other ops\n");
00660
00661 reassociate_stats.ops_eliminated
00662 += VEC_length (operand_entry_t, *ops) - 1;
00663
00664 VEC_free (operand_entry_t, heap, *ops);
00665 *ops = NULL;
00666 VEC_safe_push (operand_entry_t, heap, *ops, oelast);
00667 return;
00668 }
00669 }
00670 else if (integer_zerop (oelast->op))
00671 {
00672 if (VEC_length (operand_entry_t, *ops) != 1)
00673 {
00674 if (dump_file && (dump_flags & TDF_DETAILS))
00675 fprintf (dump_file, "Found | 0, removing\n");
00676 VEC_pop (operand_entry_t, *ops);
00677 reassociate_stats.ops_eliminated++;
00678 }
00679 }
00680 break;
00681 case MULT_EXPR:
00682 if (integer_zerop (oelast->op))
00683 {
00684 if (VEC_length (operand_entry_t, *ops) != 1)
00685 {
00686 if (dump_file && (dump_flags & TDF_DETAILS))
00687 fprintf (dump_file, "Found * 0, removing all other ops\n");
00688
00689 reassociate_stats.ops_eliminated
00690 += VEC_length (operand_entry_t, *ops) - 1;
00691 VEC_free (operand_entry_t, heap, *ops);
00692 *ops = NULL;
00693 VEC_safe_push (operand_entry_t, heap, *ops, oelast);
00694 return;
00695 }
00696 }
00697 else if (integer_onep (oelast->op))
00698 {
00699 if (VEC_length (operand_entry_t, *ops) != 1)
00700 {
00701 if (dump_file && (dump_flags & TDF_DETAILS))
00702 fprintf (dump_file, "Found * 1, removing\n");
00703 VEC_pop (operand_entry_t, *ops);
00704 reassociate_stats.ops_eliminated++;
00705 return;
00706 }
00707 }
00708 break;
00709 case BIT_XOR_EXPR:
00710 case PLUS_EXPR:
00711 case MINUS_EXPR:
00712 if (integer_zerop (oelast->op))
00713 {
00714 if (VEC_length (operand_entry_t, *ops) != 1)
00715 {
00716 if (dump_file && (dump_flags & TDF_DETAILS))
00717 fprintf (dump_file, "Found [|^+] 0, removing\n");
00718 VEC_pop (operand_entry_t, *ops);
00719 reassociate_stats.ops_eliminated++;
00720 return;
00721 }
00722 }
00723 break;
00724 default:
00725 break;
00726 }
00727 }
00728 }
00729
00730
00731
00732
00733
00734 static void
00735 optimize_ops_list (enum tree_code opcode,
00736 VEC (operand_entry_t, heap) **ops)
00737 {
00738 unsigned int length = VEC_length (operand_entry_t, *ops);
00739 unsigned int i;
00740 operand_entry_t oe;
00741 operand_entry_t oelast = NULL;
00742 bool iterate = false;
00743
00744 if (length == 1)
00745 return;
00746
00747 oelast = VEC_last (operand_entry_t, *ops);
00748
00749
00750
00751 if (oelast->rank == 0 && is_gimple_min_invariant (oelast->op))
00752 {
00753 operand_entry_t oelm1 = VEC_index (operand_entry_t, *ops, length - 2);
00754
00755 if (oelm1->rank == 0
00756 && is_gimple_min_invariant (oelm1->op)
00757 && lang_hooks.types_compatible_p (TREE_TYPE (oelm1->op),
00758 TREE_TYPE (oelast->op)))
00759 {
00760 tree folded = fold_binary (opcode, TREE_TYPE (oelm1->op),
00761 oelm1->op, oelast->op);
00762
00763 if (folded && is_gimple_min_invariant (folded))
00764 {
00765 if (dump_file && (dump_flags & TDF_DETAILS))
00766 fprintf (dump_file, "Merging constants\n");
00767
00768 VEC_pop (operand_entry_t, *ops);
00769 VEC_pop (operand_entry_t, *ops);
00770
00771 add_to_ops_vec (ops, folded);
00772 reassociate_stats.constants_eliminated++;
00773
00774 optimize_ops_list (opcode, ops);
00775 return;
00776 }
00777 }
00778 }
00779
00780 eliminate_using_constants (opcode, ops);
00781 oelast = NULL;
00782
00783 for (i = 0; VEC_iterate (operand_entry_t, *ops, i, oe);)
00784 {
00785 bool done = false;
00786
00787 if (eliminate_not_pairs (opcode, ops, i, oe))
00788 return;
00789 if (eliminate_duplicate_pair (opcode, ops, &done, i, oe, oelast)
00790 || (!done && eliminate_plus_minus_pair (opcode, ops, i, oe)))
00791 {
00792 if (done)
00793 return;
00794 iterate = true;
00795 oelast = NULL;
00796 continue;
00797 }
00798 oelast = oe;
00799 i++;
00800 }
00801
00802 length = VEC_length (operand_entry_t, *ops);
00803 oelast = VEC_last (operand_entry_t, *ops);
00804
00805 if (iterate)
00806 optimize_ops_list (opcode, ops);
00807 }
00808
00809
00810
00811
00812
00813 static bool
00814 is_phi_for_stmt (tree stmt, tree operand)
00815 {
00816 tree def_stmt;
00817 tree lhs = TREE_OPERAND (stmt, 0);
00818 use_operand_p arg_p;
00819 ssa_op_iter i;
00820
00821 if (TREE_CODE (operand) != SSA_NAME)
00822 return false;
00823
00824 def_stmt = SSA_NAME_DEF_STMT (operand);
00825 if (TREE_CODE (def_stmt) != PHI_NODE)
00826 return false;
00827
00828 FOR_EACH_PHI_ARG (arg_p, def_stmt, i, SSA_OP_USE)
00829 if (lhs == USE_FROM_PTR (arg_p))
00830 return true;
00831 return false;
00832 }
00833
00834
00835
00836
00837
00838 static void
00839 rewrite_expr_tree (tree stmt, unsigned int opindex,
00840 VEC(operand_entry_t, heap) * ops)
00841 {
00842 tree rhs = TREE_OPERAND (stmt, 1);
00843 operand_entry_t oe;
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859 if (opindex + 3 == VEC_length (operand_entry_t, ops))
00860 {
00861 operand_entry_t oe1, oe2, oe3;
00862
00863 oe1 = VEC_index (operand_entry_t, ops, opindex);
00864 oe2 = VEC_index (operand_entry_t, ops, opindex + 1);
00865 oe3 = VEC_index (operand_entry_t, ops, opindex + 2);
00866
00867 if ((oe1->rank == oe2->rank
00868 && oe2->rank != oe3->rank)
00869 || (is_phi_for_stmt (stmt, oe3->op)
00870 && !is_phi_for_stmt (stmt, oe1->op)
00871 && !is_phi_for_stmt (stmt, oe2->op)))
00872 {
00873 struct operand_entry temp = *oe3;
00874 oe3->op = oe1->op;
00875 oe3->rank = oe1->rank;
00876 oe1->op = temp.op;
00877 oe1->rank= temp.rank;
00878 }
00879 }
00880
00881
00882
00883
00884
00885
00886 if (opindex + 2 == VEC_length (operand_entry_t, ops))
00887 {
00888 operand_entry_t oe1, oe2;
00889
00890 oe1 = VEC_index (operand_entry_t, ops, opindex);
00891 oe2 = VEC_index (operand_entry_t, ops, opindex + 1);
00892
00893 if (TREE_OPERAND (rhs, 0) != oe1->op
00894 || TREE_OPERAND (rhs, 1) != oe2->op)
00895 {
00896
00897 if (dump_file && (dump_flags & TDF_DETAILS))
00898 {
00899 fprintf (dump_file, "Transforming ");
00900 print_generic_expr (dump_file, rhs, 0);
00901 }
00902
00903 TREE_OPERAND (rhs, 0) = oe1->op;
00904 TREE_OPERAND (rhs, 1) = oe2->op;
00905 update_stmt (stmt);
00906
00907 if (dump_file && (dump_flags & TDF_DETAILS))
00908 {
00909 fprintf (dump_file, " into ");
00910 print_generic_stmt (dump_file, rhs, 0);
00911 }
00912
00913 }
00914 return;
00915 }
00916
00917
00918 gcc_assert (opindex + 2 < VEC_length (operand_entry_t, ops));
00919
00920
00921 oe = VEC_index (operand_entry_t, ops, opindex);
00922
00923 if (oe->op != TREE_OPERAND (rhs, 1))
00924 {
00925
00926 if (dump_file && (dump_flags & TDF_DETAILS))
00927 {
00928 fprintf (dump_file, "Transforming ");
00929 print_generic_expr (dump_file, rhs, 0);
00930 }
00931
00932 TREE_OPERAND (rhs, 1) = oe->op;
00933 update_stmt (stmt);
00934
00935 if (dump_file && (dump_flags & TDF_DETAILS))
00936 {
00937 fprintf (dump_file, " into ");
00938 print_generic_stmt (dump_file, rhs, 0);
00939 }
00940 }
00941
00942
00943 rewrite_expr_tree (SSA_NAME_DEF_STMT (TREE_OPERAND (rhs, 0)),
00944 opindex + 1, ops);
00945 }
00946
00947
00948
00949
00950
00951 static void
00952 linearize_expr (tree stmt)
00953 {
00954 block_stmt_iterator bsinow, bsirhs;
00955 tree rhs = TREE_OPERAND (stmt, 1);
00956 enum tree_code rhscode = TREE_CODE (rhs);
00957 tree binrhs = SSA_NAME_DEF_STMT (TREE_OPERAND (rhs, 1));
00958 tree binlhs = SSA_NAME_DEF_STMT (TREE_OPERAND (rhs, 0));
00959 tree newbinrhs = NULL_TREE;
00960
00961 gcc_assert (is_reassociable_op (binlhs, TREE_CODE (rhs))
00962 && is_reassociable_op (binrhs, TREE_CODE (rhs)));
00963
00964 bsinow = bsi_for_stmt (stmt);
00965 bsirhs = bsi_for_stmt (binrhs);
00966 bsi_move_before (&bsirhs, &bsinow);
00967
00968 TREE_OPERAND (rhs, 1) = TREE_OPERAND (TREE_OPERAND (binrhs, 1), 0);
00969 if (TREE_CODE (TREE_OPERAND (rhs, 1)) == SSA_NAME)
00970 newbinrhs = SSA_NAME_DEF_STMT (TREE_OPERAND (rhs, 1));
00971 TREE_OPERAND (TREE_OPERAND (binrhs, 1), 0) = TREE_OPERAND (binlhs, 0);
00972 TREE_OPERAND (rhs, 0) = TREE_OPERAND (binrhs, 0);
00973
00974 if (dump_file && (dump_flags & TDF_DETAILS))
00975 {
00976 fprintf (dump_file, "Linearized: ");
00977 print_generic_stmt (dump_file, rhs, 0);
00978 }
00979
00980 reassociate_stats.linearized++;
00981 update_stmt (binrhs);
00982 update_stmt (binlhs);
00983 update_stmt (stmt);
00984 TREE_VISITED (binrhs) = 1;
00985 TREE_VISITED (binlhs) = 1;
00986 TREE_VISITED (stmt) = 1;
00987
00988
00989 if (newbinrhs && is_reassociable_op (newbinrhs, rhscode))
00990 linearize_expr (stmt);
00991
00992 }
00993
00994
00995
00996
00997 static tree
00998 get_single_immediate_use (tree lhs)
00999 {
01000 use_operand_p immuse;
01001 tree immusestmt;
01002
01003 if (TREE_CODE (lhs) == SSA_NAME
01004 && single_imm_use (lhs, &immuse, &immusestmt))
01005 {
01006 if (TREE_CODE (immusestmt) == RETURN_EXPR)
01007 immusestmt = TREE_OPERAND (immusestmt, 0);
01008 if (TREE_CODE (immusestmt) == MODIFY_EXPR)
01009 return immusestmt;
01010 }
01011 return NULL_TREE;
01012 }
01013 static VEC(tree, heap) *broken_up_subtracts;
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023 static tree
01024 negate_value (tree tonegate, block_stmt_iterator *bsi)
01025 {
01026 tree negatedef = tonegate;
01027 tree resultofnegate;
01028
01029 if (TREE_CODE (tonegate) == SSA_NAME)
01030 negatedef = SSA_NAME_DEF_STMT (tonegate);
01031
01032
01033
01034 if (TREE_CODE (tonegate) == SSA_NAME
01035 && TREE_CODE (negatedef) == MODIFY_EXPR
01036 && TREE_CODE (TREE_OPERAND (negatedef, 0)) == SSA_NAME
01037 && has_single_use (TREE_OPERAND (negatedef, 0))
01038 && TREE_CODE (TREE_OPERAND (negatedef, 1)) == PLUS_EXPR)
01039 {
01040 block_stmt_iterator bsi;
01041 tree binop = TREE_OPERAND (negatedef, 1);
01042
01043 bsi = bsi_for_stmt (negatedef);
01044 TREE_OPERAND (binop, 0) = negate_value (TREE_OPERAND (binop, 0),
01045 &bsi);
01046 bsi = bsi_for_stmt (negatedef);
01047 TREE_OPERAND (binop, 1) = negate_value (TREE_OPERAND (binop, 1),
01048 &bsi);
01049 update_stmt (negatedef);
01050 return TREE_OPERAND (negatedef, 0);
01051 }
01052
01053 tonegate = fold_build1 (NEGATE_EXPR, TREE_TYPE (tonegate), tonegate);
01054 resultofnegate = force_gimple_operand_bsi (bsi, tonegate, true,
01055 NULL_TREE);
01056 VEC_safe_push (tree, heap, broken_up_subtracts, resultofnegate);
01057 return resultofnegate;
01058
01059 }
01060
01061
01062
01063
01064
01065
01066
01067 static bool
01068 should_break_up_subtract (tree stmt)
01069 {
01070
01071 tree lhs = TREE_OPERAND (stmt, 0);
01072 tree rhs = TREE_OPERAND (stmt, 1);
01073 tree binlhs = TREE_OPERAND (rhs, 0);
01074 tree binrhs = TREE_OPERAND (rhs, 1);
01075 tree immusestmt;
01076
01077 if (TREE_CODE (binlhs) == SSA_NAME
01078 && is_reassociable_op (SSA_NAME_DEF_STMT (binlhs), PLUS_EXPR))
01079 return true;
01080
01081 if (TREE_CODE (binrhs) == SSA_NAME
01082 && is_reassociable_op (SSA_NAME_DEF_STMT (binrhs), PLUS_EXPR))
01083 return true;
01084
01085 if (TREE_CODE (lhs) == SSA_NAME
01086 && (immusestmt = get_single_immediate_use (lhs))
01087 && TREE_CODE (TREE_OPERAND (immusestmt, 1)) == PLUS_EXPR)
01088 return true;
01089 return false;
01090
01091 }
01092
01093
01094
01095 static void
01096 break_up_subtract (tree stmt, block_stmt_iterator *bsi)
01097 {
01098 tree rhs = TREE_OPERAND (stmt, 1);
01099
01100 if (dump_file && (dump_flags & TDF_DETAILS))
01101 {
01102 fprintf (dump_file, "Breaking up subtract ");
01103 print_generic_stmt (dump_file, stmt, 0);
01104 }
01105
01106 TREE_SET_CODE (TREE_OPERAND (stmt, 1), PLUS_EXPR);
01107 TREE_OPERAND (rhs, 1) = negate_value (TREE_OPERAND (rhs, 1), bsi);
01108
01109 update_stmt (stmt);
01110 }
01111
01112
01113
01114
01115 static void
01116 linearize_expr_tree (VEC(operand_entry_t, heap) **ops, tree stmt)
01117 {
01118 block_stmt_iterator bsinow, bsilhs;
01119 tree rhs = TREE_OPERAND (stmt, 1);
01120 tree binrhs = TREE_OPERAND (rhs, 1);
01121 tree binlhs = TREE_OPERAND (rhs, 0);
01122 tree binlhsdef, binrhsdef;
01123 bool binlhsisreassoc = false;
01124 bool binrhsisreassoc = false;
01125 enum tree_code rhscode = TREE_CODE (rhs);
01126
01127 TREE_VISITED (stmt) = 1;
01128
01129 if (TREE_CODE (binlhs) == SSA_NAME)
01130 {
01131 binlhsdef = SSA_NAME_DEF_STMT (binlhs);
01132 binlhsisreassoc = is_reassociable_op (binlhsdef, rhscode);
01133 }
01134
01135 if (TREE_CODE (binrhs) == SSA_NAME)
01136 {
01137 binrhsdef = SSA_NAME_DEF_STMT (binrhs);
01138 binrhsisreassoc = is_reassociable_op (binrhsdef, rhscode);
01139 }
01140
01141
01142
01143
01144
01145
01146
01147 if (!binlhsisreassoc)
01148 {
01149 tree temp;
01150
01151 if (!binrhsisreassoc)
01152 {
01153 add_to_ops_vec (ops, binrhs);
01154 add_to_ops_vec (ops, binlhs);
01155 return;
01156 }
01157
01158 if (dump_file && (dump_flags & TDF_DETAILS))
01159 {
01160 fprintf (dump_file, "swapping operands of ");
01161 print_generic_expr (dump_file, stmt, 0);
01162 }
01163
01164 swap_tree_operands (stmt, &TREE_OPERAND (rhs, 0),
01165 &TREE_OPERAND (rhs, 1));
01166 update_stmt (stmt);
01167
01168 if (dump_file && (dump_flags & TDF_DETAILS))
01169 {
01170 fprintf (dump_file, " is now ");
01171 print_generic_stmt (dump_file, stmt, 0);
01172 }
01173
01174
01175
01176 temp = binlhs;
01177 binlhs = binrhs;
01178 binrhs = temp;
01179 }
01180 else if (binrhsisreassoc)
01181 {
01182 linearize_expr (stmt);
01183 gcc_assert (rhs == TREE_OPERAND (stmt, 1));
01184 binlhs = TREE_OPERAND (rhs, 0);
01185 binrhs = TREE_OPERAND (rhs, 1);
01186 }
01187
01188 gcc_assert (TREE_CODE (binrhs) != SSA_NAME
01189 || !is_reassociable_op (SSA_NAME_DEF_STMT (binrhs), rhscode));
01190 bsinow = bsi_for_stmt (stmt);
01191 bsilhs = bsi_for_stmt (SSA_NAME_DEF_STMT (binlhs));
01192 bsi_move_before (&bsilhs, &bsinow);
01193 linearize_expr_tree (ops, SSA_NAME_DEF_STMT (binlhs));
01194 add_to_ops_vec (ops, binrhs);
01195 }
01196
01197
01198
01199
01200 static void
01201 repropagate_negates (void)
01202 {
01203 unsigned int i = 0;
01204 tree negate;
01205
01206 for (i = 0; VEC_iterate (tree, broken_up_subtracts, i, negate); i++)
01207 {
01208 tree user = get_single_immediate_use (negate);
01209
01210
01211
01212
01213
01214
01215 if (user
01216 && TREE_CODE (user) == MODIFY_EXPR
01217 && TREE_CODE (TREE_OPERAND (user, 1)) == PLUS_EXPR)
01218 {
01219 tree rhs = TREE_OPERAND (user, 1);
01220
01221
01222
01223
01224 if (TREE_OPERAND (TREE_OPERAND (user, 1), 0) == negate)
01225 {
01226 tree temp = TREE_OPERAND (rhs, 0);
01227 TREE_OPERAND (rhs, 0) = TREE_OPERAND (rhs, 1);
01228 TREE_OPERAND (rhs, 1) = temp;
01229 }
01230
01231
01232
01233 if (TREE_OPERAND (TREE_OPERAND (user, 1), 1) == negate)
01234 {
01235 TREE_SET_CODE (rhs, MINUS_EXPR);
01236 TREE_OPERAND (rhs, 1) = get_unary_op (negate, NEGATE_EXPR);
01237 update_stmt (user);
01238 }
01239 }
01240 }
01241 }
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258 static void
01259 break_up_subtract_bb (basic_block bb)
01260 {
01261 block_stmt_iterator bsi;
01262 basic_block son;
01263
01264 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
01265 {
01266 tree stmt = bsi_stmt (bsi);
01267
01268 if (TREE_CODE (stmt) == MODIFY_EXPR)
01269 {
01270 tree lhs = TREE_OPERAND (stmt, 0);
01271 tree rhs = TREE_OPERAND (stmt, 1);
01272
01273 TREE_VISITED (stmt) = 0;
01274
01275
01276 if ((!INTEGRAL_TYPE_P (TREE_TYPE (lhs))
01277 || !INTEGRAL_TYPE_P (TREE_TYPE (rhs)))
01278 && (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (rhs))
01279 || !SCALAR_FLOAT_TYPE_P (TREE_TYPE(lhs))
01280 || !flag_unsafe_math_optimizations))
01281 continue;
01282
01283
01284
01285
01286
01287 if (TREE_CODE (rhs) == MINUS_EXPR)
01288 if (should_break_up_subtract (stmt))
01289 break_up_subtract (stmt, &bsi);
01290 }
01291 }
01292 for (son = first_dom_son (CDI_DOMINATORS, bb);
01293 son;
01294 son = next_dom_son (CDI_DOMINATORS, son))
01295 break_up_subtract_bb (son);
01296 }
01297
01298
01299
01300
01301 static void
01302 reassociate_bb (basic_block bb)
01303 {
01304 block_stmt_iterator bsi;
01305 basic_block son;
01306
01307 for (bsi = bsi_last (bb); !bsi_end_p (bsi); bsi_prev (&bsi))
01308 {
01309 tree stmt = bsi_stmt (bsi);
01310
01311 if (TREE_CODE (stmt) == MODIFY_EXPR)
01312 {
01313 tree lhs = TREE_OPERAND (stmt, 0);
01314 tree rhs = TREE_OPERAND (stmt, 1);
01315
01316
01317
01318 if (TREE_VISITED (stmt))
01319 continue;
01320
01321
01322
01323 if ((!INTEGRAL_TYPE_P (TREE_TYPE (lhs))
01324 || !INTEGRAL_TYPE_P (TREE_TYPE (rhs)))
01325 && (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (rhs))
01326 || !SCALAR_FLOAT_TYPE_P (TREE_TYPE(lhs))
01327 || !flag_unsafe_math_optimizations))
01328 continue;
01329
01330 if (associative_tree_code (TREE_CODE (rhs)))
01331 {
01332 VEC(operand_entry_t, heap) *ops = NULL;
01333
01334
01335
01336 if (TREE_CODE (lhs) == SSA_NAME && has_zero_uses (lhs))
01337 continue;
01338
01339 TREE_VISITED (stmt) = 1;
01340 linearize_expr_tree (&ops, stmt);
01341 qsort (VEC_address (operand_entry_t, ops),
01342 VEC_length (operand_entry_t, ops),
01343 sizeof (operand_entry_t),
01344 sort_by_operand_rank);
01345 optimize_ops_list (TREE_CODE (rhs), &ops);
01346
01347 if (VEC_length (operand_entry_t, ops) == 1)
01348 {
01349 if (dump_file && (dump_flags & TDF_DETAILS))
01350 {
01351 fprintf (dump_file, "Transforming ");
01352 print_generic_expr (dump_file, rhs, 0);
01353 }
01354 TREE_OPERAND (stmt, 1) = VEC_last (operand_entry_t, ops)->op;
01355 update_stmt (stmt);
01356
01357 if (dump_file && (dump_flags & TDF_DETAILS))
01358 {
01359 fprintf (dump_file, " into ");
01360 print_generic_stmt (dump_file,
01361 TREE_OPERAND (stmt, 1), 0);
01362 }
01363 }
01364 else
01365 {
01366 rewrite_expr_tree (stmt, 0, ops);
01367 }
01368
01369 VEC_free (operand_entry_t, heap, ops);
01370 }
01371 }
01372 }
01373 for (son = first_dom_son (CDI_POST_DOMINATORS, bb);
01374 son;
01375 son = next_dom_son (CDI_POST_DOMINATORS, son))
01376 reassociate_bb (son);
01377 }
01378
01379 void dump_ops_vector (FILE *file, VEC (operand_entry_t, heap) *ops);
01380 void debug_ops_vector (VEC (operand_entry_t, heap) *ops);
01381
01382
01383
01384 void
01385 dump_ops_vector (FILE *file, VEC (operand_entry_t, heap) *ops)
01386 {
01387 operand_entry_t oe;
01388 unsigned int i;
01389
01390 for (i = 0; VEC_iterate (operand_entry_t, ops, i, oe); i++)
01391 {
01392 fprintf (file, "Op %d -> rank: %d, tree: ", i, oe->rank);
01393 print_generic_stmt (file, oe->op, 0);
01394 }
01395 }
01396
01397
01398
01399 void
01400 debug_ops_vector (VEC (operand_entry_t, heap) *ops)
01401 {
01402 dump_ops_vector (stderr, ops);
01403 }
01404
01405 static void
01406 do_reassoc (void)
01407 {
01408 break_up_subtract_bb (ENTRY_BLOCK_PTR);
01409 reassociate_bb (EXIT_BLOCK_PTR);
01410 }
01411
01412
01413
01414 static void
01415 init_reassoc (void)
01416 {
01417 int i;
01418 unsigned int rank = 2;
01419 tree param;
01420 int *bbs = XNEWVEC (int, last_basic_block + 1);
01421
01422 memset (&reassociate_stats, 0, sizeof (reassociate_stats));
01423
01424 operand_entry_pool = create_alloc_pool ("operand entry pool",
01425 sizeof (struct operand_entry), 30);
01426
01427
01428
01429 pre_and_rev_post_order_compute (NULL, bbs, false);
01430 bb_rank = XCNEWVEC (unsigned int, last_basic_block + 1);
01431
01432 operand_rank = htab_create (511, operand_entry_hash,
01433 operand_entry_eq, 0);
01434
01435
01436 for (param = DECL_ARGUMENTS (current_function_decl);
01437 param;
01438 param = TREE_CHAIN (param))
01439 {
01440 if (default_def (param) != NULL)
01441 {
01442 tree def = default_def (param);
01443 insert_operand_rank (def, ++rank);
01444 }
01445 }
01446
01447
01448 if (cfun->static_chain_decl != NULL)
01449 {
01450 tree def = default_def (cfun->static_chain_decl);
01451 if (def != NULL)
01452 insert_operand_rank (def, ++rank);
01453 }
01454
01455
01456 for (i = 0; i < n_basic_blocks - NUM_FIXED_BLOCKS; i++)
01457 bb_rank[bbs[i]] = ++rank << 16;
01458
01459 free (bbs);
01460 calculate_dominance_info (CDI_DOMINATORS);
01461 calculate_dominance_info (CDI_POST_DOMINATORS);
01462 broken_up_subtracts = NULL;
01463 }
01464
01465
01466
01467
01468 static void
01469 fini_reassoc (void)
01470 {
01471
01472 if (dump_file && (dump_flags & TDF_STATS))
01473 {
01474 fprintf (dump_file, "Reassociation stats:\n");
01475 fprintf (dump_file, "Linearized: %d\n",
01476 reassociate_stats.linearized);
01477 fprintf (dump_file, "Constants eliminated: %d\n",
01478 reassociate_stats.constants_eliminated);
01479 fprintf (dump_file, "Ops eliminated: %d\n",
01480 reassociate_stats.ops_eliminated);
01481 fprintf (dump_file, "Statements rewritten: %d\n",
01482 reassociate_stats.rewritten);
01483 }
01484 htab_delete (operand_rank);
01485
01486 free_alloc_pool (operand_entry_pool);
01487 free (bb_rank);
01488 VEC_free (tree, heap, broken_up_subtracts);
01489 free_dominance_info (CDI_POST_DOMINATORS);
01490 }
01491
01492
01493
01494 static unsigned int
01495 execute_reassoc (void)
01496 {
01497 init_reassoc ();
01498
01499 do_reassoc ();
01500 repropagate_negates ();
01501
01502 fini_reassoc ();
01503 return 0;
01504 }
01505
01506 struct tree_opt_pass pass_reassoc =
01507 {
01508 "reassoc",
01509 NULL,
01510 execute_reassoc,
01511 NULL,
01512 NULL,
01513 0,
01514 TV_TREE_REASSOC,
01515 PROP_cfg | PROP_ssa | PROP_alias,
01516 0,
01517 0,
01518 0,
01519 TODO_dump_func | TODO_ggc_collect | TODO_verify_ssa,
01520 0
01521 };