Mercurial > hg > CbC > CbC_gcc
comparison gcc/tree-ssa-phiopt.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
comparison
equal
deleted
inserted
replaced
131:84e7813d76e9 | 145:1830386684a0 |
---|---|
1 /* Optimization of PHI nodes by converting them into straightline code. | 1 /* Optimization of PHI nodes by converting them into straightline code. |
2 Copyright (C) 2004-2018 Free Software Foundation, Inc. | 2 Copyright (C) 2004-2020 Free Software Foundation, Inc. |
3 | 3 |
4 This file is part of GCC. | 4 This file is part of GCC. |
5 | 5 |
6 GCC is free software; you can redistribute it and/or modify it | 6 GCC is free software; you can redistribute it and/or modify it |
7 under the terms of the GNU General Public License as published by the | 7 under the terms of the GNU General Public License as published by the |
42 #include "domwalk.h" | 42 #include "domwalk.h" |
43 #include "cfgloop.h" | 43 #include "cfgloop.h" |
44 #include "tree-data-ref.h" | 44 #include "tree-data-ref.h" |
45 #include "tree-scalar-evolution.h" | 45 #include "tree-scalar-evolution.h" |
46 #include "tree-inline.h" | 46 #include "tree-inline.h" |
47 #include "params.h" | |
48 #include "case-cfn-macros.h" | 47 #include "case-cfn-macros.h" |
49 | 48 |
50 static unsigned int tree_ssa_phiopt_worker (bool, bool, bool); | 49 static unsigned int tree_ssa_phiopt_worker (bool, bool, bool); |
50 static bool two_value_replacement (basic_block, basic_block, edge, gphi *, | |
51 tree, tree); | |
51 static bool conditional_replacement (basic_block, basic_block, | 52 static bool conditional_replacement (basic_block, basic_block, |
52 edge, edge, gphi *, tree, tree); | 53 edge, edge, gphi *, tree, tree); |
53 static gphi *factor_out_conditional_conversion (edge, edge, gphi *, tree, tree, | 54 static gphi *factor_out_conditional_conversion (edge, edge, gphi *, tree, tree, |
54 gimple *); | 55 gimple *); |
55 static int value_replacement (basic_block, basic_block, | 56 static int value_replacement (basic_block, basic_block, |
330 arg1 = gimple_phi_arg_def (phi, e2->dest_idx); | 331 arg1 = gimple_phi_arg_def (phi, e2->dest_idx); |
331 gcc_assert (arg0 != NULL_TREE && arg1 != NULL_TREE); | 332 gcc_assert (arg0 != NULL_TREE && arg1 != NULL_TREE); |
332 } | 333 } |
333 | 334 |
334 /* Do the replacement of conditional if it can be done. */ | 335 /* Do the replacement of conditional if it can be done. */ |
335 if (!early_p | 336 if (two_value_replacement (bb, bb1, e2, phi, arg0, arg1)) |
336 && conditional_replacement (bb, bb1, e1, e2, phi, arg0, arg1)) | 337 cfgchanged = true; |
338 else if (!early_p | |
339 && conditional_replacement (bb, bb1, e1, e2, phi, | |
340 arg0, arg1)) | |
337 cfgchanged = true; | 341 cfgchanged = true; |
338 else if (abs_replacement (bb, bb1, e1, e2, phi, arg0, arg1)) | 342 else if (abs_replacement (bb, bb1, e1, e2, phi, arg0, arg1)) |
339 cfgchanged = true; | 343 cfgchanged = true; |
340 else if (!early_p | 344 else if (!early_p |
341 && cond_removal_in_popcount_pattern (bb, bb1, e1, e2, | 345 && cond_removal_in_popcount_pattern (bb, bb1, e1, e2, |
421 gimple *arg0_def_stmt = NULL, *arg1_def_stmt = NULL, *new_stmt; | 425 gimple *arg0_def_stmt = NULL, *arg1_def_stmt = NULL, *new_stmt; |
422 tree new_arg0 = NULL_TREE, new_arg1 = NULL_TREE; | 426 tree new_arg0 = NULL_TREE, new_arg1 = NULL_TREE; |
423 tree temp, result; | 427 tree temp, result; |
424 gphi *newphi; | 428 gphi *newphi; |
425 gimple_stmt_iterator gsi, gsi_for_def; | 429 gimple_stmt_iterator gsi, gsi_for_def; |
426 source_location locus = gimple_location (phi); | 430 location_t locus = gimple_location (phi); |
427 enum tree_code convert_code; | 431 enum tree_code convert_code; |
428 | 432 |
429 /* Handle only PHI statements with two arguments. TODO: If all | 433 /* Handle only PHI statements with two arguments. TODO: If all |
430 other arguments to PHI are INTEGER_CST or if their defining | 434 other arguments to PHI are INTEGER_CST or if their defining |
431 statement have the same unary operation, we can handle more | 435 statement have the same unary operation, we can handle more |
497 && gimple_bb (arg0_def_stmt) == e0->src) | 501 && gimple_bb (arg0_def_stmt) == e0->src) |
498 { | 502 { |
499 gsi = gsi_for_stmt (arg0_def_stmt); | 503 gsi = gsi_for_stmt (arg0_def_stmt); |
500 gsi_prev_nondebug (&gsi); | 504 gsi_prev_nondebug (&gsi); |
501 if (!gsi_end_p (gsi)) | 505 if (!gsi_end_p (gsi)) |
502 return NULL; | 506 { |
507 if (gassign *assign | |
508 = dyn_cast <gassign *> (gsi_stmt (gsi))) | |
509 { | |
510 tree lhs = gimple_assign_lhs (assign); | |
511 enum tree_code ass_code | |
512 = gimple_assign_rhs_code (assign); | |
513 if (ass_code != MAX_EXPR && ass_code != MIN_EXPR) | |
514 return NULL; | |
515 if (lhs != gimple_assign_rhs1 (arg0_def_stmt)) | |
516 return NULL; | |
517 gsi_prev_nondebug (&gsi); | |
518 if (!gsi_end_p (gsi)) | |
519 return NULL; | |
520 } | |
521 else | |
522 return NULL; | |
523 } | |
503 gsi = gsi_for_stmt (arg0_def_stmt); | 524 gsi = gsi_for_stmt (arg0_def_stmt); |
504 gsi_next_nondebug (&gsi); | 525 gsi_next_nondebug (&gsi); |
505 if (!gsi_end_p (gsi)) | 526 if (!gsi_end_p (gsi)) |
506 return NULL; | 527 return NULL; |
507 } | 528 } |
570 gsi = gsi_for_stmt (phi); | 591 gsi = gsi_for_stmt (phi); |
571 gsi_remove (&gsi, true); | 592 gsi_remove (&gsi, true); |
572 return newphi; | 593 return newphi; |
573 } | 594 } |
574 | 595 |
596 /* Optimize | |
597 # x_5 in range [cst1, cst2] where cst2 = cst1 + 1 | |
598 if (x_5 op cstN) # where op is == or != and N is 1 or 2 | |
599 goto bb3; | |
600 else | |
601 goto bb4; | |
602 bb3: | |
603 bb4: | |
604 # r_6 = PHI<cst3(2), cst4(3)> # where cst3 == cst4 + 1 or cst4 == cst3 + 1 | |
605 | |
606 to r_6 = x_5 + (min (cst3, cst4) - cst1) or | |
607 r_6 = (min (cst3, cst4) + cst1) - x_5 depending on op, N and which | |
608 of cst3 and cst4 is smaller. */ | |
609 | |
610 static bool | |
611 two_value_replacement (basic_block cond_bb, basic_block middle_bb, | |
612 edge e1, gphi *phi, tree arg0, tree arg1) | |
613 { | |
614 /* Only look for adjacent integer constants. */ | |
615 if (!INTEGRAL_TYPE_P (TREE_TYPE (arg0)) | |
616 || !INTEGRAL_TYPE_P (TREE_TYPE (arg1)) | |
617 || TREE_CODE (arg0) != INTEGER_CST | |
618 || TREE_CODE (arg1) != INTEGER_CST | |
619 || (tree_int_cst_lt (arg0, arg1) | |
620 ? wi::to_widest (arg0) + 1 != wi::to_widest (arg1) | |
621 : wi::to_widest (arg1) + 1 != wi::to_widest (arg0))) | |
622 return false; | |
623 | |
624 if (!empty_block_p (middle_bb)) | |
625 return false; | |
626 | |
627 gimple *stmt = last_stmt (cond_bb); | |
628 tree lhs = gimple_cond_lhs (stmt); | |
629 tree rhs = gimple_cond_rhs (stmt); | |
630 | |
631 if (TREE_CODE (lhs) != SSA_NAME | |
632 || !INTEGRAL_TYPE_P (TREE_TYPE (lhs)) | |
633 || TREE_CODE (TREE_TYPE (lhs)) == BOOLEAN_TYPE | |
634 || TREE_CODE (rhs) != INTEGER_CST) | |
635 return false; | |
636 | |
637 switch (gimple_cond_code (stmt)) | |
638 { | |
639 case EQ_EXPR: | |
640 case NE_EXPR: | |
641 break; | |
642 default: | |
643 return false; | |
644 } | |
645 | |
646 wide_int min, max; | |
647 if (get_range_info (lhs, &min, &max) != VR_RANGE | |
648 || min + 1 != max | |
649 || (wi::to_wide (rhs) != min | |
650 && wi::to_wide (rhs) != max)) | |
651 return false; | |
652 | |
653 /* We need to know which is the true edge and which is the false | |
654 edge so that we know when to invert the condition below. */ | |
655 edge true_edge, false_edge; | |
656 extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge); | |
657 if ((gimple_cond_code (stmt) == EQ_EXPR) | |
658 ^ (wi::to_wide (rhs) == max) | |
659 ^ (e1 == false_edge)) | |
660 std::swap (arg0, arg1); | |
661 | |
662 tree type; | |
663 if (TYPE_PRECISION (TREE_TYPE (lhs)) == TYPE_PRECISION (TREE_TYPE (arg0))) | |
664 { | |
665 /* Avoid performing the arithmetics in bool type which has different | |
666 semantics, otherwise prefer unsigned types from the two with | |
667 the same precision. */ | |
668 if (TREE_CODE (TREE_TYPE (arg0)) == BOOLEAN_TYPE | |
669 || !TYPE_UNSIGNED (TREE_TYPE (arg0))) | |
670 type = TREE_TYPE (lhs); | |
671 else | |
672 type = TREE_TYPE (arg0); | |
673 } | |
674 else if (TYPE_PRECISION (TREE_TYPE (lhs)) > TYPE_PRECISION (TREE_TYPE (arg0))) | |
675 type = TREE_TYPE (lhs); | |
676 else | |
677 type = TREE_TYPE (arg0); | |
678 | |
679 min = wide_int::from (min, TYPE_PRECISION (type), | |
680 TYPE_SIGN (TREE_TYPE (lhs))); | |
681 wide_int a = wide_int::from (wi::to_wide (arg0), TYPE_PRECISION (type), | |
682 TYPE_SIGN (TREE_TYPE (arg0))); | |
683 enum tree_code code; | |
684 wi::overflow_type ovf; | |
685 if (tree_int_cst_lt (arg0, arg1)) | |
686 { | |
687 code = PLUS_EXPR; | |
688 a -= min; | |
689 if (!TYPE_UNSIGNED (type)) | |
690 { | |
691 /* lhs is known to be in range [min, min+1] and we want to add a | |
692 to it. Check if that operation can overflow for those 2 values | |
693 and if yes, force unsigned type. */ | |
694 wi::add (min + (wi::neg_p (a) ? 0 : 1), a, SIGNED, &ovf); | |
695 if (ovf) | |
696 type = unsigned_type_for (type); | |
697 } | |
698 } | |
699 else | |
700 { | |
701 code = MINUS_EXPR; | |
702 a += min; | |
703 if (!TYPE_UNSIGNED (type)) | |
704 { | |
705 /* lhs is known to be in range [min, min+1] and we want to subtract | |
706 it from a. Check if that operation can overflow for those 2 | |
707 values and if yes, force unsigned type. */ | |
708 wi::sub (a, min + (wi::neg_p (min) ? 0 : 1), SIGNED, &ovf); | |
709 if (ovf) | |
710 type = unsigned_type_for (type); | |
711 } | |
712 } | |
713 | |
714 tree arg = wide_int_to_tree (type, a); | |
715 gimple_stmt_iterator gsi = gsi_for_stmt (stmt); | |
716 if (!useless_type_conversion_p (type, TREE_TYPE (lhs))) | |
717 lhs = gimplify_build1 (&gsi, NOP_EXPR, type, lhs); | |
718 tree new_rhs; | |
719 if (code == PLUS_EXPR) | |
720 new_rhs = gimplify_build2 (&gsi, PLUS_EXPR, type, lhs, arg); | |
721 else | |
722 new_rhs = gimplify_build2 (&gsi, MINUS_EXPR, type, arg, lhs); | |
723 if (!useless_type_conversion_p (TREE_TYPE (arg0), type)) | |
724 new_rhs = gimplify_build1 (&gsi, NOP_EXPR, TREE_TYPE (arg0), new_rhs); | |
725 | |
726 replace_phi_edge_with_variable (cond_bb, e1, phi, new_rhs); | |
727 | |
728 /* Note that we optimized this PHI. */ | |
729 return true; | |
730 } | |
731 | |
575 /* The function conditional_replacement does the main work of doing the | 732 /* The function conditional_replacement does the main work of doing the |
576 conditional replacement. Return true if the replacement is done. | 733 conditional replacement. Return true if the replacement is done. |
577 Otherwise return false. | 734 Otherwise return false. |
578 BB is the basic block where the replacement is going to be done on. ARG0 | 735 BB is the basic block where the replacement is going to be done on. ARG0 |
579 is argument 0 from PHI. Likewise for ARG1. */ | 736 is argument 0 from PHI. Likewise for ARG1. */ |
667 new_var = force_gimple_operand_gsi (&gsi, cond, true, NULL, true, | 824 new_var = force_gimple_operand_gsi (&gsi, cond, true, NULL, true, |
668 GSI_SAME_STMT); | 825 GSI_SAME_STMT); |
669 | 826 |
670 if (!useless_type_conversion_p (TREE_TYPE (result), TREE_TYPE (new_var))) | 827 if (!useless_type_conversion_p (TREE_TYPE (result), TREE_TYPE (new_var))) |
671 { | 828 { |
672 source_location locus_0, locus_1; | 829 location_t locus_0, locus_1; |
673 | 830 |
674 new_var2 = make_ssa_name (TREE_TYPE (result)); | 831 new_var2 = make_ssa_name (TREE_TYPE (result)); |
675 new_stmt = gimple_build_assign (new_var2, CONVERT_EXPR, new_var); | 832 new_stmt = gimple_build_assign (new_var2, CONVERT_EXPR, new_var); |
676 gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT); | 833 gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT); |
677 new_var = new_var2; | 834 new_var = new_var2; |
1202 static bool | 1359 static bool |
1203 minmax_replacement (basic_block cond_bb, basic_block middle_bb, | 1360 minmax_replacement (basic_block cond_bb, basic_block middle_bb, |
1204 edge e0, edge e1, gimple *phi, | 1361 edge e0, edge e1, gimple *phi, |
1205 tree arg0, tree arg1) | 1362 tree arg0, tree arg1) |
1206 { | 1363 { |
1207 tree result, type; | 1364 tree result, type, rhs; |
1208 gcond *cond; | 1365 gcond *cond; |
1209 gassign *new_stmt; | 1366 gassign *new_stmt; |
1210 edge true_edge, false_edge; | 1367 edge true_edge, false_edge; |
1211 enum tree_code cmp, minmax, ass_code; | 1368 enum tree_code cmp, minmax, ass_code; |
1212 tree smaller, alt_smaller, larger, alt_larger, arg_true, arg_false; | 1369 tree smaller, alt_smaller, larger, alt_larger, arg_true, arg_false; |
1218 if (HONOR_NANS (type) || HONOR_SIGNED_ZEROS (type)) | 1375 if (HONOR_NANS (type) || HONOR_SIGNED_ZEROS (type)) |
1219 return false; | 1376 return false; |
1220 | 1377 |
1221 cond = as_a <gcond *> (last_stmt (cond_bb)); | 1378 cond = as_a <gcond *> (last_stmt (cond_bb)); |
1222 cmp = gimple_cond_code (cond); | 1379 cmp = gimple_cond_code (cond); |
1380 rhs = gimple_cond_rhs (cond); | |
1381 | |
1382 /* Turn EQ/NE of extreme values to order comparisons. */ | |
1383 if ((cmp == NE_EXPR || cmp == EQ_EXPR) | |
1384 && TREE_CODE (rhs) == INTEGER_CST | |
1385 && INTEGRAL_TYPE_P (TREE_TYPE (rhs))) | |
1386 { | |
1387 if (wi::eq_p (wi::to_wide (rhs), wi::min_value (TREE_TYPE (rhs)))) | |
1388 { | |
1389 cmp = (cmp == EQ_EXPR) ? LT_EXPR : GE_EXPR; | |
1390 rhs = wide_int_to_tree (TREE_TYPE (rhs), | |
1391 wi::min_value (TREE_TYPE (rhs)) + 1); | |
1392 } | |
1393 else if (wi::eq_p (wi::to_wide (rhs), wi::max_value (TREE_TYPE (rhs)))) | |
1394 { | |
1395 cmp = (cmp == EQ_EXPR) ? GT_EXPR : LE_EXPR; | |
1396 rhs = wide_int_to_tree (TREE_TYPE (rhs), | |
1397 wi::max_value (TREE_TYPE (rhs)) - 1); | |
1398 } | |
1399 } | |
1223 | 1400 |
1224 /* This transformation is only valid for order comparisons. Record which | 1401 /* This transformation is only valid for order comparisons. Record which |
1225 operand is smaller/larger if the result of the comparison is true. */ | 1402 operand is smaller/larger if the result of the comparison is true. */ |
1226 alt_smaller = NULL_TREE; | 1403 alt_smaller = NULL_TREE; |
1227 alt_larger = NULL_TREE; | 1404 alt_larger = NULL_TREE; |
1228 if (cmp == LT_EXPR || cmp == LE_EXPR) | 1405 if (cmp == LT_EXPR || cmp == LE_EXPR) |
1229 { | 1406 { |
1230 smaller = gimple_cond_lhs (cond); | 1407 smaller = gimple_cond_lhs (cond); |
1231 larger = gimple_cond_rhs (cond); | 1408 larger = rhs; |
1232 /* If we have smaller < CST it is equivalent to smaller <= CST-1. | 1409 /* If we have smaller < CST it is equivalent to smaller <= CST-1. |
1233 Likewise smaller <= CST is equivalent to smaller < CST+1. */ | 1410 Likewise smaller <= CST is equivalent to smaller < CST+1. */ |
1234 if (TREE_CODE (larger) == INTEGER_CST) | 1411 if (TREE_CODE (larger) == INTEGER_CST |
1412 && INTEGRAL_TYPE_P (TREE_TYPE (larger))) | |
1235 { | 1413 { |
1236 if (cmp == LT_EXPR) | 1414 if (cmp == LT_EXPR) |
1237 { | 1415 { |
1238 wi::overflow_type overflow; | 1416 wi::overflow_type overflow; |
1239 wide_int alt = wi::sub (wi::to_wide (larger), 1, | 1417 wide_int alt = wi::sub (wi::to_wide (larger), 1, |
1253 } | 1431 } |
1254 } | 1432 } |
1255 } | 1433 } |
1256 else if (cmp == GT_EXPR || cmp == GE_EXPR) | 1434 else if (cmp == GT_EXPR || cmp == GE_EXPR) |
1257 { | 1435 { |
1258 smaller = gimple_cond_rhs (cond); | 1436 smaller = rhs; |
1259 larger = gimple_cond_lhs (cond); | 1437 larger = gimple_cond_lhs (cond); |
1260 /* If we have larger > CST it is equivalent to larger >= CST+1. | 1438 /* If we have larger > CST it is equivalent to larger >= CST+1. |
1261 Likewise larger >= CST is equivalent to larger > CST-1. */ | 1439 Likewise larger >= CST is equivalent to larger > CST-1. */ |
1262 if (TREE_CODE (smaller) == INTEGER_CST) | 1440 if (TREE_CODE (smaller) == INTEGER_CST |
1441 && INTEGRAL_TYPE_P (TREE_TYPE (smaller))) | |
1263 { | 1442 { |
1264 wi::overflow_type overflow; | 1443 wi::overflow_type overflow; |
1265 if (cmp == GT_EXPR) | 1444 if (cmp == GT_EXPR) |
1266 { | 1445 { |
1267 wide_int alt = wi::add (wi::to_wide (smaller), 1, | 1446 wide_int alt = wi::add (wi::to_wide (smaller), 1, |
1690 | 1869 |
1691 /* OTHER_BLOCK must have only one executable statement which must have the | 1870 /* OTHER_BLOCK must have only one executable statement which must have the |
1692 form arg0 = -arg1 or arg1 = -arg0. */ | 1871 form arg0 = -arg1 or arg1 = -arg0. */ |
1693 | 1872 |
1694 assign = last_and_only_stmt (middle_bb); | 1873 assign = last_and_only_stmt (middle_bb); |
1695 /* If we did not find the proper negation assignment, then we can not | 1874 /* If we did not find the proper negation assignment, then we cannot |
1696 optimize. */ | 1875 optimize. */ |
1697 if (assign == NULL) | 1876 if (assign == NULL) |
1698 return false; | 1877 return false; |
1699 | 1878 |
1700 /* If we got here, then we have found the only executable statement | 1879 /* If we got here, then we have found the only executable statement |
1701 in OTHER_BLOCK. If it is anything other than arg = -arg1 or | 1880 in OTHER_BLOCK. If it is anything other than arg = -arg1 or |
1702 arg1 = -arg0, then we can not optimize. */ | 1881 arg1 = -arg0, then we cannot optimize. */ |
1703 if (gimple_code (assign) != GIMPLE_ASSIGN) | 1882 if (gimple_code (assign) != GIMPLE_ASSIGN) |
1704 return false; | 1883 return false; |
1705 | 1884 |
1706 lhs = gimple_assign_lhs (assign); | 1885 lhs = gimple_assign_lhs (assign); |
1707 | 1886 |
2017 JOIN_BB: | 2196 JOIN_BB: |
2018 some more | 2197 some more |
2019 | 2198 |
2020 We check that MIDDLE_BB contains only one store, that that store | 2199 We check that MIDDLE_BB contains only one store, that that store |
2021 doesn't trap (not via NOTRAP, but via checking if an access to the same | 2200 doesn't trap (not via NOTRAP, but via checking if an access to the same |
2022 memory location dominates us) and that the store has a "simple" RHS. */ | 2201 memory location dominates us, or the store is to a local addressable |
2202 object) and that the store has a "simple" RHS. */ | |
2023 | 2203 |
2024 static bool | 2204 static bool |
2025 cond_store_replacement (basic_block middle_bb, basic_block join_bb, | 2205 cond_store_replacement (basic_block middle_bb, basic_block join_bb, |
2026 edge e0, edge e1, hash_set<tree> *nontrap) | 2206 edge e0, edge e1, hash_set<tree> *nontrap) |
2027 { | 2207 { |
2028 gimple *assign = last_and_only_stmt (middle_bb); | 2208 gimple *assign = last_and_only_stmt (middle_bb); |
2029 tree lhs, rhs, name, name2; | 2209 tree lhs, rhs, name, name2; |
2030 gphi *newphi; | 2210 gphi *newphi; |
2031 gassign *new_stmt; | 2211 gassign *new_stmt; |
2032 gimple_stmt_iterator gsi; | 2212 gimple_stmt_iterator gsi; |
2033 source_location locus; | 2213 location_t locus; |
2034 | 2214 |
2035 /* Check if middle_bb contains of only one store. */ | 2215 /* Check if middle_bb contains of only one store. */ |
2036 if (!assign | 2216 if (!assign |
2037 || !gimple_assign_single_p (assign) | 2217 || !gimple_assign_single_p (assign) |
2038 || gimple_has_volatile_ops (assign)) | 2218 || gimple_has_volatile_ops (assign)) |
2039 return false; | 2219 return false; |
2040 | 2220 |
2221 /* And no PHI nodes so all uses in the single stmt are also | |
2222 available where we insert to. */ | |
2223 if (!gimple_seq_empty_p (phi_nodes (middle_bb))) | |
2224 return false; | |
2225 | |
2041 locus = gimple_location (assign); | 2226 locus = gimple_location (assign); |
2042 lhs = gimple_assign_lhs (assign); | 2227 lhs = gimple_assign_lhs (assign); |
2043 rhs = gimple_assign_rhs1 (assign); | 2228 rhs = gimple_assign_rhs1 (assign); |
2044 if (TREE_CODE (lhs) != MEM_REF | 2229 if ((TREE_CODE (lhs) != MEM_REF |
2045 || TREE_CODE (TREE_OPERAND (lhs, 0)) != SSA_NAME | 2230 && TREE_CODE (lhs) != ARRAY_REF |
2231 && TREE_CODE (lhs) != COMPONENT_REF) | |
2046 || !is_gimple_reg_type (TREE_TYPE (lhs))) | 2232 || !is_gimple_reg_type (TREE_TYPE (lhs))) |
2047 return false; | 2233 return false; |
2048 | 2234 |
2049 /* Prove that we can move the store down. We could also check | 2235 /* Prove that we can move the store down. We could also check |
2050 TREE_THIS_NOTRAP here, but in that case we also could move stores, | 2236 TREE_THIS_NOTRAP here, but in that case we also could move stores, |
2051 whose value is not available readily, which we want to avoid. */ | 2237 whose value is not available readily, which we want to avoid. */ |
2052 if (!nontrap->contains (lhs)) | 2238 if (!nontrap->contains (lhs)) |
2053 return false; | 2239 { |
2240 /* If LHS is a local variable without address-taken, we could | |
2241 always safely move down the store. */ | |
2242 tree base = get_base_address (lhs); | |
2243 if (!auto_var_p (base) || TREE_ADDRESSABLE (base)) | |
2244 return false; | |
2245 } | |
2054 | 2246 |
2055 /* Now we've checked the constraints, so do the transformation: | 2247 /* Now we've checked the constraints, so do the transformation: |
2056 1) Remove the single store. */ | 2248 1) Remove the single store. */ |
2057 gsi = gsi_for_stmt (assign); | 2249 gsi = gsi_for_stmt (assign); |
2058 unlink_stmt_vdef (assign); | 2250 unlink_stmt_vdef (assign); |
2078 /* 2) Insert a load from the memory of the store to the temporary | 2270 /* 2) Insert a load from the memory of the store to the temporary |
2079 on the edge which did not contain the store. */ | 2271 on the edge which did not contain the store. */ |
2080 name = make_temp_ssa_name (TREE_TYPE (lhs), NULL, "cstore"); | 2272 name = make_temp_ssa_name (TREE_TYPE (lhs), NULL, "cstore"); |
2081 new_stmt = gimple_build_assign (name, lhs); | 2273 new_stmt = gimple_build_assign (name, lhs); |
2082 gimple_set_location (new_stmt, locus); | 2274 gimple_set_location (new_stmt, locus); |
2275 lhs = unshare_expr (lhs); | |
2276 /* Set TREE_NO_WARNING on the rhs of the load to avoid uninit | |
2277 warnings. */ | |
2278 TREE_NO_WARNING (gimple_assign_rhs1 (new_stmt)) = 1; | |
2083 gsi_insert_on_edge (e1, new_stmt); | 2279 gsi_insert_on_edge (e1, new_stmt); |
2084 | 2280 |
2085 /* 3) Create a PHI node at the join block, with one argument | 2281 /* 3) Create a PHI node at the join block, with one argument |
2086 holding the old RHS, and the other holding the temporary | 2282 holding the old RHS, and the other holding the temporary |
2087 where we stored the old memory contents. */ | 2283 where we stored the old memory contents. */ |
2088 name2 = make_temp_ssa_name (TREE_TYPE (lhs), NULL, "cstore"); | 2284 name2 = make_temp_ssa_name (TREE_TYPE (lhs), NULL, "cstore"); |
2089 newphi = create_phi_node (name2, join_bb); | 2285 newphi = create_phi_node (name2, join_bb); |
2090 add_phi_arg (newphi, rhs, e0, locus); | 2286 add_phi_arg (newphi, rhs, e0, locus); |
2091 add_phi_arg (newphi, name, e1, locus); | 2287 add_phi_arg (newphi, name, e1, locus); |
2092 | 2288 |
2093 lhs = unshare_expr (lhs); | |
2094 new_stmt = gimple_build_assign (lhs, PHI_RESULT (newphi)); | 2289 new_stmt = gimple_build_assign (lhs, PHI_RESULT (newphi)); |
2095 | 2290 |
2096 /* 4) Insert that PHI node. */ | 2291 /* 4) Insert that PHI node. */ |
2097 gsi = gsi_after_labels (join_bb); | 2292 gsi = gsi_after_labels (join_bb); |
2098 if (gsi_end_p (gsi)) | 2293 if (gsi_end_p (gsi)) |
2100 gsi = gsi_last_bb (join_bb); | 2295 gsi = gsi_last_bb (join_bb); |
2101 gsi_insert_after (&gsi, new_stmt, GSI_NEW_STMT); | 2296 gsi_insert_after (&gsi, new_stmt, GSI_NEW_STMT); |
2102 } | 2297 } |
2103 else | 2298 else |
2104 gsi_insert_before (&gsi, new_stmt, GSI_NEW_STMT); | 2299 gsi_insert_before (&gsi, new_stmt, GSI_NEW_STMT); |
2300 | |
2301 if (dump_file && (dump_flags & TDF_DETAILS)) | |
2302 { | |
2303 fprintf (dump_file, "\nConditional store replacement happened!"); | |
2304 fprintf (dump_file, "\nReplaced the store with a load."); | |
2305 fprintf (dump_file, "\nInserted a new PHI statement in joint block:\n"); | |
2306 print_gimple_stmt (dump_file, new_stmt, 0, TDF_VOPS|TDF_MEMSYMS); | |
2307 } | |
2105 | 2308 |
2106 return true; | 2309 return true; |
2107 } | 2310 } |
2108 | 2311 |
2109 /* Do the main work of conditional store replacement. */ | 2312 /* Do the main work of conditional store replacement. */ |
2112 cond_if_else_store_replacement_1 (basic_block then_bb, basic_block else_bb, | 2315 cond_if_else_store_replacement_1 (basic_block then_bb, basic_block else_bb, |
2113 basic_block join_bb, gimple *then_assign, | 2316 basic_block join_bb, gimple *then_assign, |
2114 gimple *else_assign) | 2317 gimple *else_assign) |
2115 { | 2318 { |
2116 tree lhs_base, lhs, then_rhs, else_rhs, name; | 2319 tree lhs_base, lhs, then_rhs, else_rhs, name; |
2117 source_location then_locus, else_locus; | 2320 location_t then_locus, else_locus; |
2118 gimple_stmt_iterator gsi; | 2321 gimple_stmt_iterator gsi; |
2119 gphi *newphi; | 2322 gphi *newphi; |
2120 gassign *new_stmt; | 2323 gassign *new_stmt; |
2121 | 2324 |
2122 if (then_assign == NULL | 2325 if (then_assign == NULL |
2267 if (else_assign) | 2470 if (else_assign) |
2268 return cond_if_else_store_replacement_1 (then_bb, else_bb, join_bb, | 2471 return cond_if_else_store_replacement_1 (then_bb, else_bb, join_bb, |
2269 then_assign, else_assign); | 2472 then_assign, else_assign); |
2270 } | 2473 } |
2271 | 2474 |
2272 if (MAX_STORES_TO_SINK == 0) | 2475 /* If either vectorization or if-conversion is disabled then do |
2476 not sink any stores. */ | |
2477 if (param_max_stores_to_sink == 0 | |
2478 || (!flag_tree_loop_vectorize && !flag_tree_slp_vectorize) | |
2479 || !flag_tree_loop_if_convert) | |
2273 return false; | 2480 return false; |
2274 | 2481 |
2275 /* Find data references. */ | 2482 /* Find data references. */ |
2276 then_datarefs.create (1); | 2483 then_datarefs.create (1); |
2277 else_datarefs.create (1); | 2484 else_datarefs.create (1); |
2324 else_stores.safe_push (else_store); | 2531 else_stores.safe_push (else_store); |
2325 } | 2532 } |
2326 | 2533 |
2327 /* No pairs of stores found. */ | 2534 /* No pairs of stores found. */ |
2328 if (!then_stores.length () | 2535 if (!then_stores.length () |
2329 || then_stores.length () > (unsigned) MAX_STORES_TO_SINK) | 2536 || then_stores.length () > (unsigned) param_max_stores_to_sink) |
2330 { | 2537 { |
2331 free_data_refs (then_datarefs); | 2538 free_data_refs (then_datarefs); |
2332 free_data_refs (else_datarefs); | 2539 free_data_refs (else_datarefs); |
2333 return false; | 2540 return false; |
2334 } | 2541 } |
2454 | 2661 |
2455 static void | 2662 static void |
2456 hoist_adjacent_loads (basic_block bb0, basic_block bb1, | 2663 hoist_adjacent_loads (basic_block bb0, basic_block bb1, |
2457 basic_block bb2, basic_block bb3) | 2664 basic_block bb2, basic_block bb3) |
2458 { | 2665 { |
2459 int param_align = PARAM_VALUE (PARAM_L1_CACHE_LINE_SIZE); | 2666 int param_align = param_l1_cache_line_size; |
2460 unsigned param_align_bits = (unsigned) (param_align * BITS_PER_UNIT); | 2667 unsigned param_align_bits = (unsigned) (param_align * BITS_PER_UNIT); |
2461 gphi_iterator gsi; | 2668 gphi_iterator gsi; |
2462 | 2669 |
2463 /* Walk the phis in bb3 looking for an opportunity. We are looking | 2670 /* Walk the phis in bb3 looking for an opportunity. We are looking |
2464 for phis of two SSA names, one each of which is defined in bb1 and | 2671 for phis of two SSA names, one each of which is defined in bb1 and |
2604 | 2811 |
2605 static bool | 2812 static bool |
2606 gate_hoist_loads (void) | 2813 gate_hoist_loads (void) |
2607 { | 2814 { |
2608 return (flag_hoist_adjacent_loads == 1 | 2815 return (flag_hoist_adjacent_loads == 1 |
2609 && PARAM_VALUE (PARAM_L1_CACHE_LINE_SIZE) | 2816 && param_l1_cache_line_size |
2610 && HAVE_conditional_move); | 2817 && HAVE_conditional_move); |
2611 } | 2818 } |
2612 | 2819 |
2613 /* This pass tries to replaces an if-then-else block with an | 2820 /* This pass tries to replaces an if-then-else block with an |
2614 assignment. We have four kinds of transformations. Some of these | 2821 assignment. We have four kinds of transformations. Some of these |