Mercurial > hg > CbC > CbC_gcc
comparison gcc/ipa-cp.c @ 132:d34655255c78
update gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 10:21:07 +0900 |
parents | 84e7813d76e9 |
children | 1830386684a0 |
comparison
equal
deleted
inserted
replaced
130:e108057fa461 | 132:d34655255c78 |
---|---|
1 /* Interprocedural constant propagation | 1 /* Interprocedural constant propagation |
2 Copyright (C) 2005-2017 Free Software Foundation, Inc. | 2 Copyright (C) 2005-2018 Free Software Foundation, Inc. |
3 | 3 |
4 Contributed by Razya Ladelsky <RAZYA@il.ibm.com> and Martin Jambor | 4 Contributed by Razya Ladelsky <RAZYA@il.ibm.com> and Martin Jambor |
5 <mjambor@suse.cz> | 5 <mjambor@suse.cz> |
6 | 6 |
7 This file is part of GCC. | 7 This file is part of GCC. |
312 inline bool bottom_p () const; | 312 inline bool bottom_p () const; |
313 inline bool top_p () const; | 313 inline bool top_p () const; |
314 inline bool set_to_bottom (); | 314 inline bool set_to_bottom (); |
315 bool meet_with (const value_range *p_vr); | 315 bool meet_with (const value_range *p_vr); |
316 bool meet_with (const ipcp_vr_lattice &other); | 316 bool meet_with (const ipcp_vr_lattice &other); |
317 void init () { m_vr.type = VR_UNDEFINED; } | 317 void init () { gcc_assert (m_vr.undefined_p ()); } |
318 void print (FILE * f); | 318 void print (FILE * f); |
319 | 319 |
320 private: | 320 private: |
321 bool meet_with_1 (const value_range *other_vr); | 321 bool meet_with_1 (const value_range *other_vr); |
322 }; | 322 }; |
403 { | 403 { |
404 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | 404 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); |
405 return &plats->ctxlat; | 405 return &plats->ctxlat; |
406 } | 406 } |
407 | 407 |
408 /* Return the lattice corresponding to the value range of the Ith formal | |
409 parameter of the function described by INFO. */ | |
410 | |
411 static inline ipcp_vr_lattice * | |
412 ipa_get_vr_lat (struct ipa_node_params *info, int i) | |
413 { | |
414 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | |
415 return &plats->m_value_range; | |
416 } | |
417 | |
418 /* Return whether LAT is a lattice with a single constant and without an | 408 /* Return whether LAT is a lattice with a single constant and without an |
419 undefined value. */ | 409 undefined value. */ |
420 | 410 |
421 template <typename valtype> | 411 template <typename valtype> |
422 inline bool | 412 inline bool |
495 { | 485 { |
496 ipcp_value_source<valtype> *s; | 486 ipcp_value_source<valtype> *s; |
497 | 487 |
498 fprintf (f, " [from:"); | 488 fprintf (f, " [from:"); |
499 for (s = val->sources; s; s = s->next) | 489 for (s = val->sources; s; s = s->next) |
500 fprintf (f, " %i(%i)", s->cs->caller->order, | 490 fprintf (f, " %i(%f)", s->cs->caller->order, |
501 s->cs->frequency); | 491 s->cs->sreal_frequency ().to_double ()); |
502 fprintf (f, "]"); | 492 fprintf (f, "]"); |
503 } | 493 } |
504 | 494 |
505 if (dump_benefits) | 495 if (dump_benefits) |
506 fprintf (f, " [loc_time: %i, loc_size: %i, " | 496 fprintf (f, " [loc_time: %i, loc_size: %i, " |
628 /* TODO: call is versionable if we make sure that all | 618 /* TODO: call is versionable if we make sure that all |
629 callers are inside of a comdat group. */ | 619 callers are inside of a comdat group. */ |
630 reason = "calls comdat-local function"; | 620 reason = "calls comdat-local function"; |
631 } | 621 } |
632 | 622 |
623 /* Functions calling BUILT_IN_VA_ARG_PACK and BUILT_IN_VA_ARG_PACK_LEN | |
624 work only when inlined. Cloning them may still lead to better code | |
625 because ipa-cp will not give up on cloning further. If the function is | |
626 external this however leads to wrong code because we may end up producing | |
627 offline copy of the function. */ | |
628 if (DECL_EXTERNAL (node->decl)) | |
629 for (cgraph_edge *edge = node->callees; !reason && edge; | |
630 edge = edge->next_callee) | |
631 if (fndecl_built_in_p (edge->callee->decl, BUILT_IN_NORMAL)) | |
632 { | |
633 if (DECL_FUNCTION_CODE (edge->callee->decl) == BUILT_IN_VA_ARG_PACK) | |
634 reason = "external function which calls va_arg_pack"; | |
635 if (DECL_FUNCTION_CODE (edge->callee->decl) | |
636 == BUILT_IN_VA_ARG_PACK_LEN) | |
637 reason = "external function which calls va_arg_pack_len"; | |
638 } | |
639 | |
633 if (reason && dump_file && !node->alias && !node->thunk.thunk_p) | 640 if (reason && dump_file && !node->alias && !node->thunk.thunk_p) |
634 fprintf (dump_file, "Function %s is not versionable, reason: %s.\n", | 641 fprintf (dump_file, "Function %s is not versionable, reason: %s.\n", |
635 node->dump_name (), reason); | 642 node->dump_name (), reason); |
636 | 643 |
637 info->versionable = (reason == NULL); | 644 info->versionable = (reason == NULL); |
675 struct cgraph_edge *cs; | 682 struct cgraph_edge *cs; |
676 | 683 |
677 for (cs = node->callers; cs; cs = cs->next_caller) | 684 for (cs = node->callers; cs; cs = cs->next_caller) |
678 if (!cs->caller->thunk.thunk_p) | 685 if (!cs->caller->thunk.thunk_p) |
679 { | 686 { |
680 if (cs->count.initialized_p ()) | 687 if (cs->count.ipa ().initialized_p ()) |
681 stats->count_sum += cs->count; | 688 stats->count_sum += cs->count.ipa (); |
682 stats->freq_sum += cs->frequency; | 689 stats->freq_sum += cs->frequency (); |
683 stats->n_calls++; | 690 stats->n_calls++; |
684 if (cs->maybe_hot_p ()) | 691 if (cs->maybe_hot_p ()) |
685 stats->n_hot_calls ++; | 692 stats->n_hot_calls ++; |
686 } | 693 } |
687 return false; | 694 return false; |
729 /* When profile is available and function is hot, propagate into it even if | 736 /* When profile is available and function is hot, propagate into it even if |
730 calls seems cold; constant propagation can improve function's speed | 737 calls seems cold; constant propagation can improve function's speed |
731 significantly. */ | 738 significantly. */ |
732 if (max_count > profile_count::zero ()) | 739 if (max_count > profile_count::zero ()) |
733 { | 740 { |
734 if (stats.count_sum > node->count.apply_scale (90, 100)) | 741 if (stats.count_sum > node->count.ipa ().apply_scale (90, 100)) |
735 { | 742 { |
736 if (dump_file) | 743 if (dump_file) |
737 fprintf (dump_file, "Considering %s for cloning; " | 744 fprintf (dump_file, "Considering %s for cloning; " |
738 "usually called directly.\n", | 745 "usually called directly.\n", |
739 node->name ()); | 746 node->name ()); |
905 ipcp_vr_lattice::meet_with (const value_range *p_vr) | 912 ipcp_vr_lattice::meet_with (const value_range *p_vr) |
906 { | 913 { |
907 return meet_with_1 (p_vr); | 914 return meet_with_1 (p_vr); |
908 } | 915 } |
909 | 916 |
910 /* Meet the current value of the lattice with value ranfge described by | 917 /* Meet the current value of the lattice with value range described by |
911 OTHER_VR lattice. */ | 918 OTHER_VR lattice. Return TRUE if anything changed. */ |
912 | 919 |
913 bool | 920 bool |
914 ipcp_vr_lattice::meet_with_1 (const value_range *other_vr) | 921 ipcp_vr_lattice::meet_with_1 (const value_range *other_vr) |
915 { | 922 { |
916 tree min = m_vr.min, max = m_vr.max; | |
917 value_range_type type = m_vr.type; | |
918 | |
919 if (bottom_p ()) | 923 if (bottom_p ()) |
920 return false; | 924 return false; |
921 | 925 |
922 if (other_vr->type == VR_VARYING) | 926 if (other_vr->varying_p ()) |
923 return set_to_bottom (); | 927 return set_to_bottom (); |
924 | 928 |
925 vrp_meet (&m_vr, other_vr); | 929 value_range save (m_vr); |
926 if (type != m_vr.type | 930 m_vr.union_ (other_vr); |
927 || min != m_vr.min | 931 return !m_vr.ignore_equivs_equal_p (save); |
928 || max != m_vr.max) | |
929 return true; | |
930 else | |
931 return false; | |
932 } | 932 } |
933 | 933 |
934 /* Return true if value range information in the lattice is yet unknown. */ | 934 /* Return true if value range information in the lattice is yet unknown. */ |
935 | 935 |
936 bool | 936 bool |
937 ipcp_vr_lattice::top_p () const | 937 ipcp_vr_lattice::top_p () const |
938 { | 938 { |
939 return m_vr.type == VR_UNDEFINED; | 939 return m_vr.undefined_p (); |
940 } | 940 } |
941 | 941 |
942 /* Return true if value range information in the lattice is known to be | 942 /* Return true if value range information in the lattice is known to be |
943 unusable. */ | 943 unusable. */ |
944 | 944 |
945 bool | 945 bool |
946 ipcp_vr_lattice::bottom_p () const | 946 ipcp_vr_lattice::bottom_p () const |
947 { | 947 { |
948 return m_vr.type == VR_VARYING; | 948 return m_vr.varying_p (); |
949 } | 949 } |
950 | 950 |
951 /* Set value range information in the lattice to bottom. Return true if it | 951 /* Set value range information in the lattice to bottom. Return true if it |
952 previously was in a different state. */ | 952 previously was in a different state. */ |
953 | 953 |
954 bool | 954 bool |
955 ipcp_vr_lattice::set_to_bottom () | 955 ipcp_vr_lattice::set_to_bottom () |
956 { | 956 { |
957 if (m_vr.type == VR_VARYING) | 957 if (m_vr.varying_p ()) |
958 return false; | 958 return false; |
959 m_vr.type = VR_VARYING; | 959 m_vr.set_varying (); |
960 return true; | 960 return true; |
961 } | 961 } |
962 | 962 |
963 /* Set lattice value to bottom, if it already isn't the case. */ | 963 /* Set lattice value to bottom, if it already isn't the case. */ |
964 | 964 |
1157 struct cgraph_edge *ie; | 1157 struct cgraph_edge *ie; |
1158 bool disable = false, variable = false; | 1158 bool disable = false, variable = false; |
1159 int i; | 1159 int i; |
1160 | 1160 |
1161 gcc_checking_assert (node->has_gimple_body_p ()); | 1161 gcc_checking_assert (node->has_gimple_body_p ()); |
1162 if (cgraph_local_p (node)) | 1162 if (node->local.local) |
1163 { | 1163 { |
1164 int caller_count = 0; | 1164 int caller_count = 0; |
1165 node->call_for_symbol_thunks_and_aliases (count_callers, &caller_count, | 1165 node->call_for_symbol_thunks_and_aliases (count_callers, &caller_count, |
1166 true); | 1166 true); |
1167 gcc_checking_assert (caller_count > 0); | 1167 gcc_checking_assert (caller_count > 0); |
1218 ie->indirect_info->param_index)->virt_call = 1; | 1218 ie->indirect_info->param_index)->virt_call = 1; |
1219 } | 1219 } |
1220 } | 1220 } |
1221 | 1221 |
1222 /* Return the result of a (possibly arithmetic) pass through jump function | 1222 /* Return the result of a (possibly arithmetic) pass through jump function |
1223 JFUNC on the constant value INPUT. Return NULL_TREE if that cannot be | 1223 JFUNC on the constant value INPUT. RES_TYPE is the type of the parameter |
1224 to which the result is passed. Return NULL_TREE if that cannot be | |
1224 determined or be considered an interprocedural invariant. */ | 1225 determined or be considered an interprocedural invariant. */ |
1225 | 1226 |
1226 static tree | 1227 static tree |
1227 ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input) | 1228 ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input, |
1228 { | 1229 tree res_type) |
1229 tree restype, res; | 1230 { |
1231 tree res; | |
1230 | 1232 |
1231 if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR) | 1233 if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR) |
1232 return input; | 1234 return input; |
1233 if (!is_gimple_ip_invariant (input)) | 1235 if (!is_gimple_ip_invariant (input)) |
1234 return NULL_TREE; | 1236 return NULL_TREE; |
1235 | 1237 |
1236 if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc)) | 1238 tree_code opcode = ipa_get_jf_pass_through_operation (jfunc); |
1237 == tcc_unary) | 1239 if (!res_type) |
1238 res = fold_unary (ipa_get_jf_pass_through_operation (jfunc), | 1240 { |
1239 TREE_TYPE (input), input); | 1241 if (TREE_CODE_CLASS (opcode) == tcc_comparison) |
1242 res_type = boolean_type_node; | |
1243 else if (expr_type_first_operand_type_p (opcode)) | |
1244 res_type = TREE_TYPE (input); | |
1245 else | |
1246 return NULL_TREE; | |
1247 } | |
1248 | |
1249 if (TREE_CODE_CLASS (opcode) == tcc_unary) | |
1250 res = fold_unary (opcode, res_type, input); | |
1240 else | 1251 else |
1241 { | 1252 res = fold_binary (opcode, res_type, input, |
1242 if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc)) | 1253 ipa_get_jf_pass_through_operand (jfunc)); |
1243 == tcc_comparison) | 1254 |
1244 restype = boolean_type_node; | |
1245 else | |
1246 restype = TREE_TYPE (input); | |
1247 res = fold_binary (ipa_get_jf_pass_through_operation (jfunc), restype, | |
1248 input, ipa_get_jf_pass_through_operand (jfunc)); | |
1249 } | |
1250 if (res && !is_gimple_ip_invariant (res)) | 1255 if (res && !is_gimple_ip_invariant (res)) |
1251 return NULL_TREE; | 1256 return NULL_TREE; |
1252 | 1257 |
1253 return res; | 1258 return res; |
1254 } | 1259 } |
1273 } | 1278 } |
1274 | 1279 |
1275 /* Determine whether JFUNC evaluates to a single known constant value and if | 1280 /* Determine whether JFUNC evaluates to a single known constant value and if |
1276 so, return it. Otherwise return NULL. INFO describes the caller node or | 1281 so, return it. Otherwise return NULL. INFO describes the caller node or |
1277 the one it is inlined to, so that pass-through jump functions can be | 1282 the one it is inlined to, so that pass-through jump functions can be |
1278 evaluated. */ | 1283 evaluated. PARM_TYPE is the type of the parameter to which the result is |
1284 passed. */ | |
1279 | 1285 |
1280 tree | 1286 tree |
1281 ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc) | 1287 ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc, |
1288 tree parm_type) | |
1282 { | 1289 { |
1283 if (jfunc->type == IPA_JF_CONST) | 1290 if (jfunc->type == IPA_JF_CONST) |
1284 return ipa_get_jf_constant (jfunc); | 1291 return ipa_get_jf_constant (jfunc); |
1285 else if (jfunc->type == IPA_JF_PASS_THROUGH | 1292 else if (jfunc->type == IPA_JF_PASS_THROUGH |
1286 || jfunc->type == IPA_JF_ANCESTOR) | 1293 || jfunc->type == IPA_JF_ANCESTOR) |
1310 | 1317 |
1311 if (!input) | 1318 if (!input) |
1312 return NULL_TREE; | 1319 return NULL_TREE; |
1313 | 1320 |
1314 if (jfunc->type == IPA_JF_PASS_THROUGH) | 1321 if (jfunc->type == IPA_JF_PASS_THROUGH) |
1315 return ipa_get_jf_pass_through_result (jfunc, input); | 1322 return ipa_get_jf_pass_through_result (jfunc, input, parm_type); |
1316 else | 1323 else |
1317 return ipa_get_jf_ancestor_result (jfunc, input); | 1324 return ipa_get_jf_ancestor_result (jfunc, input); |
1318 } | 1325 } |
1319 else | 1326 else |
1320 return NULL_TREE; | 1327 return NULL_TREE; |
1560 return true; | 1567 return true; |
1561 } | 1568 } |
1562 | 1569 |
1563 /* Propagate values through a pass-through jump function JFUNC associated with | 1570 /* Propagate values through a pass-through jump function JFUNC associated with |
1564 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX | 1571 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX |
1565 is the index of the source parameter. */ | 1572 is the index of the source parameter. PARM_TYPE is the type of the |
1573 parameter to which the result is passed. */ | |
1566 | 1574 |
1567 static bool | 1575 static bool |
1568 propagate_vals_across_pass_through (cgraph_edge *cs, ipa_jump_func *jfunc, | 1576 propagate_vals_across_pass_through (cgraph_edge *cs, ipa_jump_func *jfunc, |
1569 ipcp_lattice<tree> *src_lat, | 1577 ipcp_lattice<tree> *src_lat, |
1570 ipcp_lattice<tree> *dest_lat, int src_idx) | 1578 ipcp_lattice<tree> *dest_lat, int src_idx, |
1579 tree parm_type) | |
1571 { | 1580 { |
1572 ipcp_value<tree> *src_val; | 1581 ipcp_value<tree> *src_val; |
1573 bool ret = false; | 1582 bool ret = false; |
1574 | 1583 |
1575 /* Do not create new values when propagating within an SCC because if there | 1584 /* Do not create new values when propagating within an SCC because if there |
1576 are arithmetic functions with circular dependencies, there is infinite | 1585 are arithmetic functions with circular dependencies, there is infinite |
1577 number of them and we would just make lattices bottom. */ | 1586 number of them and we would just make lattices bottom. If this condition |
1587 is ever relaxed we have to detect self-feeding recursive calls in | |
1588 cgraph_edge_brings_value_p in a smarter way. */ | |
1578 if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR) | 1589 if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR) |
1579 && ipa_edge_within_scc (cs)) | 1590 && ipa_edge_within_scc (cs)) |
1580 ret = dest_lat->set_contains_variable (); | 1591 ret = dest_lat->set_contains_variable (); |
1581 else | 1592 else |
1582 for (src_val = src_lat->values; src_val; src_val = src_val->next) | 1593 for (src_val = src_lat->values; src_val; src_val = src_val->next) |
1583 { | 1594 { |
1584 tree cstval = ipa_get_jf_pass_through_result (jfunc, src_val->value); | 1595 tree cstval = ipa_get_jf_pass_through_result (jfunc, src_val->value, |
1596 parm_type); | |
1585 | 1597 |
1586 if (cstval) | 1598 if (cstval) |
1587 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx); | 1599 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx); |
1588 else | 1600 else |
1589 ret |= dest_lat->set_contains_variable (); | 1601 ret |= dest_lat->set_contains_variable (); |
1620 | 1632 |
1621 return ret; | 1633 return ret; |
1622 } | 1634 } |
1623 | 1635 |
1624 /* Propagate scalar values across jump function JFUNC that is associated with | 1636 /* Propagate scalar values across jump function JFUNC that is associated with |
1625 edge CS and put the values into DEST_LAT. */ | 1637 edge CS and put the values into DEST_LAT. PARM_TYPE is the type of the |
1638 parameter to which the result is passed. */ | |
1626 | 1639 |
1627 static bool | 1640 static bool |
1628 propagate_scalar_across_jump_function (struct cgraph_edge *cs, | 1641 propagate_scalar_across_jump_function (struct cgraph_edge *cs, |
1629 struct ipa_jump_func *jfunc, | 1642 struct ipa_jump_func *jfunc, |
1630 ipcp_lattice<tree> *dest_lat) | 1643 ipcp_lattice<tree> *dest_lat, |
1644 tree param_type) | |
1631 { | 1645 { |
1632 if (dest_lat->bottom) | 1646 if (dest_lat->bottom) |
1633 return false; | 1647 return false; |
1634 | 1648 |
1635 if (jfunc->type == IPA_JF_CONST) | 1649 if (jfunc->type == IPA_JF_CONST) |
1660 || (src_lat->values_count > 1))) | 1674 || (src_lat->values_count > 1))) |
1661 return dest_lat->set_contains_variable (); | 1675 return dest_lat->set_contains_variable (); |
1662 | 1676 |
1663 if (jfunc->type == IPA_JF_PASS_THROUGH) | 1677 if (jfunc->type == IPA_JF_PASS_THROUGH) |
1664 ret = propagate_vals_across_pass_through (cs, jfunc, src_lat, | 1678 ret = propagate_vals_across_pass_through (cs, jfunc, src_lat, |
1665 dest_lat, src_idx); | 1679 dest_lat, src_idx, param_type); |
1666 else | 1680 else |
1667 ret = propagate_vals_across_ancestor (cs, jfunc, src_lat, dest_lat, | 1681 ret = propagate_vals_across_ancestor (cs, jfunc, src_lat, dest_lat, |
1668 src_idx); | 1682 src_idx); |
1669 | 1683 |
1670 if (src_lat->contains_variable) | 1684 if (src_lat->contains_variable) |
1779 enum availability availability; | 1793 enum availability availability; |
1780 cgraph_node *callee = cs->callee->function_symbol (&availability); | 1794 cgraph_node *callee = cs->callee->function_symbol (&availability); |
1781 struct ipa_node_params *callee_info = IPA_NODE_REF (callee); | 1795 struct ipa_node_params *callee_info = IPA_NODE_REF (callee); |
1782 tree parm_type = ipa_get_type (callee_info, idx); | 1796 tree parm_type = ipa_get_type (callee_info, idx); |
1783 | 1797 |
1784 /* For K&R C programs, ipa_get_type() could return NULL_TREE. | 1798 /* For K&R C programs, ipa_get_type() could return NULL_TREE. Avoid the |
1785 Avoid the transform for these cases. */ | 1799 transform for these cases. Similarly, we can have bad type mismatches |
1786 if (!parm_type) | 1800 with LTO, avoid doing anything with those too. */ |
1801 if (!parm_type | |
1802 || (!INTEGRAL_TYPE_P (parm_type) && !POINTER_TYPE_P (parm_type))) | |
1787 { | 1803 { |
1788 if (dump_file && (dump_flags & TDF_DETAILS)) | 1804 if (dump_file && (dump_flags & TDF_DETAILS)) |
1789 fprintf (dump_file, "Setting dest_lattice to bottom, because" | 1805 fprintf (dump_file, "Setting dest_lattice to bottom, because type of " |
1790 " param %i type is NULL for %s\n", idx, | 1806 "param %i of %s is NULL or unsuitable for bits propagation\n", |
1791 cs->callee->name ()); | 1807 idx, cs->callee->name ()); |
1792 | 1808 |
1793 return dest_lattice->set_to_bottom (); | 1809 return dest_lattice->set_to_bottom (); |
1794 } | 1810 } |
1795 | 1811 |
1796 unsigned precision = TYPE_PRECISION (parm_type); | 1812 unsigned precision = TYPE_PRECISION (parm_type); |
1857 static bool | 1873 static bool |
1858 ipa_vr_operation_and_type_effects (value_range *dst_vr, value_range *src_vr, | 1874 ipa_vr_operation_and_type_effects (value_range *dst_vr, value_range *src_vr, |
1859 enum tree_code operation, | 1875 enum tree_code operation, |
1860 tree dst_type, tree src_type) | 1876 tree dst_type, tree src_type) |
1861 { | 1877 { |
1862 memset (dst_vr, 0, sizeof (*dst_vr)); | 1878 *dst_vr = value_range (); |
1863 extract_range_from_unary_expr (dst_vr, operation, dst_type, src_vr, src_type); | 1879 extract_range_from_unary_expr (dst_vr, operation, dst_type, src_vr, src_type); |
1864 if (dst_vr->type == VR_RANGE || dst_vr->type == VR_ANTI_RANGE) | 1880 if (dst_vr->varying_p () || dst_vr->undefined_p ()) |
1865 return true; | |
1866 else | |
1867 return false; | 1881 return false; |
1882 return true; | |
1868 } | 1883 } |
1869 | 1884 |
1870 /* Propagate value range across jump function JFUNC that is associated with | 1885 /* Propagate value range across jump function JFUNC that is associated with |
1871 edge CS with param of callee of PARAM_TYPE and update DEST_PLATS | 1886 edge CS with param of callee of PARAM_TYPE and update DEST_PLATS |
1872 accordingly. */ | 1887 accordingly. */ |
1915 { | 1930 { |
1916 val = fold_convert (param_type, val); | 1931 val = fold_convert (param_type, val); |
1917 if (TREE_OVERFLOW_P (val)) | 1932 if (TREE_OVERFLOW_P (val)) |
1918 val = drop_tree_overflow (val); | 1933 val = drop_tree_overflow (val); |
1919 | 1934 |
1920 value_range tmpvr; | 1935 value_range tmpvr (VR_RANGE, val, val); |
1921 memset (&tmpvr, 0, sizeof (tmpvr)); | |
1922 tmpvr.type = VR_RANGE; | |
1923 tmpvr.min = val; | |
1924 tmpvr.max = val; | |
1925 return dest_lat->meet_with (&tmpvr); | 1936 return dest_lat->meet_with (&tmpvr); |
1926 } | 1937 } |
1927 } | 1938 } |
1928 | 1939 |
1929 value_range vr; | 1940 value_range vr; |
1930 if (jfunc->m_vr | 1941 if (jfunc->m_vr |
1931 && ipa_vr_operation_and_type_effects (&vr, jfunc->m_vr, NOP_EXPR, | 1942 && ipa_vr_operation_and_type_effects (&vr, jfunc->m_vr, NOP_EXPR, |
1932 param_type, | 1943 param_type, |
1933 TREE_TYPE (jfunc->m_vr->min))) | 1944 jfunc->m_vr->type ())) |
1934 return dest_lat->meet_with (&vr); | 1945 return dest_lat->meet_with (&vr); |
1935 else | 1946 else |
1936 return dest_lat->set_to_bottom (); | 1947 return dest_lat->set_to_bottom (); |
1937 } | 1948 } |
1938 | 1949 |
2235 args_count = ipa_get_cs_argument_count (args); | 2246 args_count = ipa_get_cs_argument_count (args); |
2236 parms_count = ipa_get_param_count (callee_info); | 2247 parms_count = ipa_get_param_count (callee_info); |
2237 if (parms_count == 0) | 2248 if (parms_count == 0) |
2238 return false; | 2249 return false; |
2239 | 2250 |
2240 /* No propagation through instrumentation thunks is available yet. | |
2241 It should be possible with proper mapping of call args and | |
2242 instrumented callee params in the propagation loop below. But | |
2243 this case mostly occurs when legacy code calls instrumented code | |
2244 and it is not a primary target for optimizations. | |
2245 We detect instrumentation thunks in aliases and thunks chain by | |
2246 checking instrumentation_clone flag for chain source and target. | |
2247 Going through instrumentation thunks we always have it changed | |
2248 from 0 to 1 and all other nodes do not change it. */ | |
2249 if (!cs->callee->instrumentation_clone | |
2250 && callee->instrumentation_clone) | |
2251 { | |
2252 for (i = 0; i < parms_count; i++) | |
2253 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, | |
2254 i)); | |
2255 return ret; | |
2256 } | |
2257 | |
2258 /* If this call goes through a thunk we must not propagate to the first (0th) | 2251 /* If this call goes through a thunk we must not propagate to the first (0th) |
2259 parameter. However, we might need to uncover a thunk from below a series | 2252 parameter. However, we might need to uncover a thunk from below a series |
2260 of aliases first. */ | 2253 of aliases first. */ |
2261 if (call_passes_through_thunk_p (cs)) | 2254 if (call_passes_through_thunk_p (cs)) |
2262 { | 2255 { |
2277 if (availability == AVAIL_INTERPOSABLE) | 2270 if (availability == AVAIL_INTERPOSABLE) |
2278 ret |= set_all_contains_variable (dest_plats); | 2271 ret |= set_all_contains_variable (dest_plats); |
2279 else | 2272 else |
2280 { | 2273 { |
2281 ret |= propagate_scalar_across_jump_function (cs, jump_func, | 2274 ret |= propagate_scalar_across_jump_function (cs, jump_func, |
2282 &dest_plats->itself); | 2275 &dest_plats->itself, |
2276 param_type); | |
2283 ret |= propagate_context_across_jump_function (cs, jump_func, i, | 2277 ret |= propagate_context_across_jump_function (cs, jump_func, i, |
2284 &dest_plats->ctxlat); | 2278 &dest_plats->ctxlat); |
2285 ret | 2279 ret |
2286 |= propagate_bits_across_jump_function (cs, i, jump_func, | 2280 |= propagate_bits_across_jump_function (cs, i, jump_func, |
2287 &dest_plats->bits_lattice); | 2281 &dest_plats->bits_lattice); |
2892 if (dump_file) | 2886 if (dump_file) |
2893 fprintf (dump_file, " Decided to specialize for all " | 2887 fprintf (dump_file, " Decided to specialize for all " |
2894 "known contexts, code not going to grow.\n"); | 2888 "known contexts, code not going to grow.\n"); |
2895 } | 2889 } |
2896 else if (good_cloning_opportunity_p (node, | 2890 else if (good_cloning_opportunity_p (node, |
2897 MAX ((base_time - time).to_int (), | 2891 MIN ((base_time - time).to_int (), |
2898 65536), | 2892 65536), |
2899 stats.freq_sum, stats.count_sum, | 2893 stats.freq_sum, stats.count_sum, |
2900 size)) | 2894 size)) |
2901 { | 2895 { |
2902 if (size + overall_size <= max_new_size) | 2896 if (size + overall_size <= max_new_size) |
3255 struct cgraph_node *node; | 3249 struct cgraph_node *node; |
3256 | 3250 |
3257 if (dump_file) | 3251 if (dump_file) |
3258 fprintf (dump_file, "\n Propagating constants:\n\n"); | 3252 fprintf (dump_file, "\n Propagating constants:\n\n"); |
3259 | 3253 |
3254 max_count = profile_count::uninitialized (); | |
3255 | |
3260 FOR_EACH_DEFINED_FUNCTION (node) | 3256 FOR_EACH_DEFINED_FUNCTION (node) |
3261 { | 3257 { |
3262 struct ipa_node_params *info = IPA_NODE_REF (node); | 3258 struct ipa_node_params *info = IPA_NODE_REF (node); |
3263 | 3259 |
3264 determine_versionability (node, info); | 3260 determine_versionability (node, info); |
3266 { | 3262 { |
3267 info->lattices = XCNEWVEC (struct ipcp_param_lattices, | 3263 info->lattices = XCNEWVEC (struct ipcp_param_lattices, |
3268 ipa_get_param_count (info)); | 3264 ipa_get_param_count (info)); |
3269 initialize_node_lattices (node); | 3265 initialize_node_lattices (node); |
3270 } | 3266 } |
3271 if (node->definition && !node->alias) | 3267 ipa_fn_summary *s = ipa_fn_summaries->get (node); |
3272 overall_size += ipa_fn_summaries->get (node)->self_size; | 3268 if (node->definition && !node->alias && s != NULL) |
3273 if (node->count > max_count) | 3269 overall_size += s->self_size; |
3274 max_count = node->count; | 3270 max_count = max_count.max (node->count.ipa ()); |
3275 } | 3271 } |
3276 | 3272 |
3277 max_new_size = overall_size; | 3273 max_new_size = overall_size; |
3278 if (max_new_size < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS)) | 3274 if (max_new_size < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS)) |
3279 max_new_size = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS); | 3275 max_new_size = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS); |
3354 /* Turning calls to direct calls will improve overall summary. */ | 3350 /* Turning calls to direct calls will improve overall summary. */ |
3355 if (found) | 3351 if (found) |
3356 ipa_update_overall_fn_summary (node); | 3352 ipa_update_overall_fn_summary (node); |
3357 } | 3353 } |
3358 | 3354 |
3359 /* Vector of pointers which for linked lists of clones of an original crgaph | 3355 class edge_clone_summary; |
3360 edge. */ | 3356 static call_summary <edge_clone_summary *> *edge_clone_summaries = NULL; |
3361 | 3357 |
3362 static vec<cgraph_edge *> next_edge_clone; | 3358 /* Edge clone summary. */ |
3363 static vec<cgraph_edge *> prev_edge_clone; | 3359 |
3364 | 3360 struct edge_clone_summary |
3365 static inline void | 3361 { |
3366 grow_edge_clone_vectors (void) | 3362 /* Default constructor. */ |
3367 { | 3363 edge_clone_summary (): prev_clone (NULL), next_clone (NULL) {} |
3368 if (next_edge_clone.length () | 3364 |
3369 <= (unsigned) symtab->edges_max_uid) | 3365 /* Default destructor. */ |
3370 next_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1); | 3366 ~edge_clone_summary () |
3371 if (prev_edge_clone.length () | 3367 { |
3372 <= (unsigned) symtab->edges_max_uid) | 3368 if (prev_clone) |
3373 prev_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1); | 3369 edge_clone_summaries->get (prev_clone)->next_clone = next_clone; |
3374 } | 3370 if (next_clone) |
3375 | 3371 edge_clone_summaries->get (next_clone)->prev_clone = prev_clone; |
3376 /* Edge duplication hook to grow the appropriate linked list in | 3372 } |
3377 next_edge_clone. */ | 3373 |
3378 | 3374 cgraph_edge *prev_clone; |
3379 static void | 3375 cgraph_edge *next_clone; |
3380 ipcp_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst, | 3376 }; |
3381 void *) | 3377 |
3382 { | 3378 class edge_clone_summary_t: |
3383 grow_edge_clone_vectors (); | 3379 public call_summary <edge_clone_summary *> |
3384 | 3380 { |
3385 struct cgraph_edge *old_next = next_edge_clone[src->uid]; | 3381 public: |
3386 if (old_next) | 3382 edge_clone_summary_t (symbol_table *symtab): |
3387 prev_edge_clone[old_next->uid] = dst; | 3383 call_summary <edge_clone_summary *> (symtab) |
3388 prev_edge_clone[dst->uid] = src; | 3384 { |
3389 | 3385 m_initialize_when_cloning = true; |
3390 next_edge_clone[dst->uid] = old_next; | 3386 } |
3391 next_edge_clone[src->uid] = dst; | 3387 |
3392 } | 3388 virtual void duplicate (cgraph_edge *src_edge, cgraph_edge *dst_edge, |
3393 | 3389 edge_clone_summary *src_data, |
3394 /* Hook that is called by cgraph.c when an edge is removed. */ | 3390 edge_clone_summary *dst_data); |
3395 | 3391 }; |
3396 static void | 3392 |
3397 ipcp_edge_removal_hook (struct cgraph_edge *cs, void *) | 3393 /* Edge duplication hook. */ |
3398 { | 3394 |
3399 grow_edge_clone_vectors (); | 3395 void |
3400 | 3396 edge_clone_summary_t::duplicate (cgraph_edge *src_edge, cgraph_edge *dst_edge, |
3401 struct cgraph_edge *prev = prev_edge_clone[cs->uid]; | 3397 edge_clone_summary *src_data, |
3402 struct cgraph_edge *next = next_edge_clone[cs->uid]; | 3398 edge_clone_summary *dst_data) |
3403 if (prev) | 3399 { |
3404 next_edge_clone[prev->uid] = next; | 3400 if (src_data->next_clone) |
3405 if (next) | 3401 edge_clone_summaries->get (src_data->next_clone)->prev_clone = dst_edge; |
3406 prev_edge_clone[next->uid] = prev; | 3402 dst_data->prev_clone = src_edge; |
3403 dst_data->next_clone = src_data->next_clone; | |
3404 src_data->next_clone = dst_edge; | |
3407 } | 3405 } |
3408 | 3406 |
3409 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a | 3407 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a |
3410 parameter with the given INDEX. */ | 3408 parameter with the given INDEX. */ |
3411 | 3409 |
3436 | 3434 |
3437 struct ipa_node_params *info = IPA_NODE_REF (node); | 3435 struct ipa_node_params *info = IPA_NODE_REF (node); |
3438 return info->is_all_contexts_clone && info->ipcp_orig_node == dest; | 3436 return info->is_all_contexts_clone && info->ipcp_orig_node == dest; |
3439 } | 3437 } |
3440 | 3438 |
3441 /* Return true if edge CS does bring about the value described by SRC to node | 3439 /* Return true if edge CS does bring about the value described by SRC to |
3442 DEST or its clone for all contexts. */ | 3440 DEST_VAL of node DEST or its clone for all contexts. */ |
3443 | 3441 |
3444 static bool | 3442 static bool |
3445 cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source<tree> *src, | 3443 cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source<tree> *src, |
3446 cgraph_node *dest) | 3444 cgraph_node *dest, ipcp_value<tree> *dest_val) |
3447 { | 3445 { |
3448 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); | 3446 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); |
3449 enum availability availability; | 3447 enum availability availability; |
3450 cgraph_node *real_dest = cs->callee->function_symbol (&availability); | 3448 cgraph_node *real_dest = cs->callee->function_symbol (&availability); |
3451 | 3449 |
3452 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest) | 3450 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest) |
3453 || availability <= AVAIL_INTERPOSABLE | 3451 || availability <= AVAIL_INTERPOSABLE |
3454 || caller_info->node_dead) | 3452 || caller_info->node_dead) |
3455 return false; | 3453 return false; |
3454 | |
3456 if (!src->val) | 3455 if (!src->val) |
3457 return true; | 3456 return true; |
3458 | 3457 |
3459 if (caller_info->ipcp_orig_node) | 3458 if (caller_info->ipcp_orig_node) |
3460 { | 3459 { |
3466 return (t != NULL_TREE | 3465 return (t != NULL_TREE |
3467 && values_equal_for_ipcp_p (src->val->value, t)); | 3466 && values_equal_for_ipcp_p (src->val->value, t)); |
3468 } | 3467 } |
3469 else | 3468 else |
3470 { | 3469 { |
3470 /* At the moment we do not propagate over arithmetic jump functions in | |
3471 SCCs, so it is safe to detect self-feeding recursive calls in this | |
3472 way. */ | |
3473 if (src->val == dest_val) | |
3474 return true; | |
3475 | |
3471 struct ipcp_agg_lattice *aglat; | 3476 struct ipcp_agg_lattice *aglat; |
3472 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info, | 3477 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info, |
3473 src->index); | 3478 src->index); |
3474 if (src->offset == -1) | 3479 if (src->offset == -1) |
3475 return (plats->itself.is_single_const () | 3480 return (plats->itself.is_single_const () |
3487 } | 3492 } |
3488 return false; | 3493 return false; |
3489 } | 3494 } |
3490 } | 3495 } |
3491 | 3496 |
3492 /* Return true if edge CS does bring about the value described by SRC to node | 3497 /* Return true if edge CS does bring about the value described by SRC to |
3493 DEST or its clone for all contexts. */ | 3498 DST_VAL of node DEST or its clone for all contexts. */ |
3494 | 3499 |
3495 static bool | 3500 static bool |
3496 cgraph_edge_brings_value_p (cgraph_edge *cs, | 3501 cgraph_edge_brings_value_p (cgraph_edge *cs, |
3497 ipcp_value_source<ipa_polymorphic_call_context> *src, | 3502 ipcp_value_source<ipa_polymorphic_call_context> *src, |
3498 cgraph_node *dest) | 3503 cgraph_node *dest, |
3504 ipcp_value<ipa_polymorphic_call_context> *) | |
3499 { | 3505 { |
3500 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); | 3506 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); |
3501 cgraph_node *real_dest = cs->callee->function_symbol (); | 3507 cgraph_node *real_dest = cs->callee->function_symbol (); |
3502 | 3508 |
3503 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest) | 3509 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest) |
3521 /* Get the next clone in the linked list of clones of an edge. */ | 3527 /* Get the next clone in the linked list of clones of an edge. */ |
3522 | 3528 |
3523 static inline struct cgraph_edge * | 3529 static inline struct cgraph_edge * |
3524 get_next_cgraph_edge_clone (struct cgraph_edge *cs) | 3530 get_next_cgraph_edge_clone (struct cgraph_edge *cs) |
3525 { | 3531 { |
3526 return next_edge_clone[cs->uid]; | 3532 edge_clone_summary *s = edge_clone_summaries->get (cs); |
3527 } | 3533 return s != NULL ? s->next_clone : NULL; |
3528 | 3534 } |
3529 /* Given VAL that is intended for DEST, iterate over all its sources and if | 3535 |
3530 they still hold, add their edge frequency and their number into *FREQUENCY | 3536 /* Given VAL that is intended for DEST, iterate over all its sources and if any |
3531 and *CALLER_COUNT respectively. */ | 3537 of them is viable and hot, return true. In that case, for those that still |
3538 hold, add their edge frequency and their number into *FREQUENCY and | |
3539 *CALLER_COUNT respectively. */ | |
3532 | 3540 |
3533 template <typename valtype> | 3541 template <typename valtype> |
3534 static bool | 3542 static bool |
3535 get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest, | 3543 get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest, |
3536 int *freq_sum, | 3544 int *freq_sum, |
3538 { | 3546 { |
3539 ipcp_value_source<valtype> *src; | 3547 ipcp_value_source<valtype> *src; |
3540 int freq = 0, count = 0; | 3548 int freq = 0, count = 0; |
3541 profile_count cnt = profile_count::zero (); | 3549 profile_count cnt = profile_count::zero (); |
3542 bool hot = false; | 3550 bool hot = false; |
3551 bool non_self_recursive = false; | |
3543 | 3552 |
3544 for (src = val->sources; src; src = src->next) | 3553 for (src = val->sources; src; src = src->next) |
3545 { | 3554 { |
3546 struct cgraph_edge *cs = src->cs; | 3555 struct cgraph_edge *cs = src->cs; |
3547 while (cs) | 3556 while (cs) |
3548 { | 3557 { |
3549 if (cgraph_edge_brings_value_p (cs, src, dest)) | 3558 if (cgraph_edge_brings_value_p (cs, src, dest, val)) |
3550 { | 3559 { |
3551 count++; | 3560 count++; |
3552 freq += cs->frequency; | 3561 freq += cs->frequency (); |
3553 if (cs->count.initialized_p ()) | 3562 if (cs->count.ipa ().initialized_p ()) |
3554 cnt += cs->count; | 3563 cnt += cs->count.ipa (); |
3555 hot |= cs->maybe_hot_p (); | 3564 hot |= cs->maybe_hot_p (); |
3565 if (cs->caller != dest) | |
3566 non_self_recursive = true; | |
3556 } | 3567 } |
3557 cs = get_next_cgraph_edge_clone (cs); | 3568 cs = get_next_cgraph_edge_clone (cs); |
3558 } | 3569 } |
3559 } | 3570 } |
3571 | |
3572 /* If the only edges bringing a value are self-recursive ones, do not bother | |
3573 evaluating it. */ | |
3574 if (!non_self_recursive) | |
3575 return false; | |
3560 | 3576 |
3561 *freq_sum = freq; | 3577 *freq_sum = freq; |
3562 *count_sum = cnt; | 3578 *count_sum = cnt; |
3563 *caller_count = count; | 3579 *caller_count = count; |
3564 return hot; | 3580 return hot; |
3579 for (src = val->sources; src; src = src->next) | 3595 for (src = val->sources; src; src = src->next) |
3580 { | 3596 { |
3581 struct cgraph_edge *cs = src->cs; | 3597 struct cgraph_edge *cs = src->cs; |
3582 while (cs) | 3598 while (cs) |
3583 { | 3599 { |
3584 if (cgraph_edge_brings_value_p (cs, src, dest)) | 3600 if (cgraph_edge_brings_value_p (cs, src, dest, val)) |
3585 ret.quick_push (cs); | 3601 ret.quick_push (cs); |
3586 cs = get_next_cgraph_edge_clone (cs); | 3602 cs = get_next_cgraph_edge_clone (cs); |
3587 } | 3603 } |
3588 } | 3604 } |
3589 | 3605 |
3659 struct cgraph_edge *cs; | 3675 struct cgraph_edge *cs; |
3660 struct caller_statistics stats; | 3676 struct caller_statistics stats; |
3661 profile_count new_sum, orig_sum; | 3677 profile_count new_sum, orig_sum; |
3662 profile_count remainder, orig_node_count = orig_node->count; | 3678 profile_count remainder, orig_node_count = orig_node->count; |
3663 | 3679 |
3664 if (!(orig_node_count > profile_count::zero ())) | 3680 if (!(orig_node_count.ipa () > profile_count::zero ())) |
3665 return; | 3681 return; |
3666 | 3682 |
3667 init_caller_stats (&stats); | 3683 init_caller_stats (&stats); |
3668 orig_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, | 3684 orig_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, |
3669 false); | 3685 false); |
3692 orig_node_count.dump (dump_file); | 3708 orig_node_count.dump (dump_file); |
3693 fprintf (dump_file, "\n"); | 3709 fprintf (dump_file, "\n"); |
3694 } | 3710 } |
3695 } | 3711 } |
3696 | 3712 |
3697 new_node->count = new_sum; | 3713 remainder = orig_node_count.combine_with_ipa_count (orig_node_count.ipa () |
3698 remainder = orig_node_count - new_sum; | 3714 - new_sum.ipa ()); |
3715 new_sum = orig_node_count.combine_with_ipa_count (new_sum); | |
3699 orig_node->count = remainder; | 3716 orig_node->count = remainder; |
3700 | 3717 |
3701 for (cs = new_node->callees; cs; cs = cs->next_callee) | 3718 for (cs = new_node->callees; cs; cs = cs->next_callee) |
3702 /* FIXME: why we care about non-zero frequency here? */ | 3719 cs->count = cs->count.apply_scale (new_sum, orig_node_count); |
3703 if (cs->frequency) | |
3704 cs->count = cs->count.apply_scale (new_sum, orig_node_count); | |
3705 else | |
3706 cs->count = profile_count::zero (); | |
3707 | 3720 |
3708 for (cs = orig_node->callees; cs; cs = cs->next_callee) | 3721 for (cs = orig_node->callees; cs; cs = cs->next_callee) |
3709 cs->count = cs->count.apply_scale (remainder, orig_node_count); | 3722 cs->count = cs->count.apply_scale (remainder, orig_node_count); |
3710 | 3723 |
3711 if (dump_file) | 3724 if (dump_file) |
3738 new_node_count = new_node->count; | 3751 new_node_count = new_node->count; |
3739 new_node->count += redirected_sum; | 3752 new_node->count += redirected_sum; |
3740 orig_node->count -= redirected_sum; | 3753 orig_node->count -= redirected_sum; |
3741 | 3754 |
3742 for (cs = new_node->callees; cs; cs = cs->next_callee) | 3755 for (cs = new_node->callees; cs; cs = cs->next_callee) |
3743 if (cs->frequency) | 3756 cs->count += cs->count.apply_scale (redirected_sum, new_node_count); |
3744 cs->count += cs->count.apply_scale (redirected_sum, new_node_count); | |
3745 else | |
3746 cs->count = profile_count::zero (); | |
3747 | 3757 |
3748 for (cs = orig_node->callees; cs; cs = cs->next_callee) | 3758 for (cs = orig_node->callees; cs; cs = cs->next_callee) |
3749 { | 3759 { |
3750 profile_count dec = cs->count.apply_scale (redirected_sum, | 3760 profile_count dec = cs->count.apply_scale (redirected_sum, |
3751 orig_node_count); | 3761 orig_node_count); |
3805 replace_map = get_replacement_map (info, t, i); | 3815 replace_map = get_replacement_map (info, t, i); |
3806 if (replace_map) | 3816 if (replace_map) |
3807 vec_safe_push (replace_trees, replace_map); | 3817 vec_safe_push (replace_trees, replace_map); |
3808 } | 3818 } |
3809 } | 3819 } |
3820 auto_vec<cgraph_edge *, 2> self_recursive_calls; | |
3821 for (i = callers.length () - 1; i >= 0; i--) | |
3822 { | |
3823 cgraph_edge *cs = callers[i]; | |
3824 if (cs->caller == node) | |
3825 { | |
3826 self_recursive_calls.safe_push (cs); | |
3827 callers.unordered_remove (i); | |
3828 } | |
3829 } | |
3810 | 3830 |
3811 new_node = node->create_virtual_clone (callers, replace_trees, | 3831 new_node = node->create_virtual_clone (callers, replace_trees, |
3812 args_to_skip, "constprop"); | 3832 args_to_skip, "constprop"); |
3833 | |
3834 bool have_self_recursive_calls = !self_recursive_calls.is_empty (); | |
3835 for (unsigned j = 0; j < self_recursive_calls.length (); j++) | |
3836 { | |
3837 cgraph_edge *cs = get_next_cgraph_edge_clone (self_recursive_calls[j]); | |
3838 /* Cloned edges can disappear during cloning as speculation can be | |
3839 resolved, check that we have one and that it comes from the last | |
3840 cloning. */ | |
3841 if (cs && cs->caller == new_node) | |
3842 cs->redirect_callee_duplicating_thunks (new_node); | |
3843 /* Any future code that would make more than one clone of an outgoing | |
3844 edge would confuse this mechanism, so let's check that does not | |
3845 happen. */ | |
3846 gcc_checking_assert (!cs | |
3847 || !get_next_cgraph_edge_clone (cs) | |
3848 || get_next_cgraph_edge_clone (cs)->caller != new_node); | |
3849 } | |
3850 if (have_self_recursive_calls) | |
3851 new_node->expand_all_artificial_thunks (); | |
3852 | |
3813 ipa_set_node_agg_value_chain (new_node, aggvals); | 3853 ipa_set_node_agg_value_chain (new_node, aggvals); |
3814 for (av = aggvals; av; av = av->next) | 3854 for (av = aggvals; av; av = av->next) |
3815 new_node->maybe_create_reference (av->value, NULL); | 3855 new_node->maybe_create_reference (av->value, NULL); |
3816 | 3856 |
3817 if (dump_file && (dump_flags & TDF_DETAILS)) | 3857 if (dump_file && (dump_flags & TDF_DETAILS)) |
3840 | 3880 |
3841 callers.release (); | 3881 callers.release (); |
3842 return new_node; | 3882 return new_node; |
3843 } | 3883 } |
3844 | 3884 |
3885 /* Return true, if JFUNC, which describes a i-th parameter of call CS, is a | |
3886 simple no-operation pass-through function to itself. */ | |
3887 | |
3888 static bool | |
3889 self_recursive_pass_through_p (cgraph_edge *cs, ipa_jump_func *jfunc, int i) | |
3890 { | |
3891 enum availability availability; | |
3892 if (cs->caller == cs->callee->function_symbol (&availability) | |
3893 && availability > AVAIL_INTERPOSABLE | |
3894 && jfunc->type == IPA_JF_PASS_THROUGH | |
3895 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR | |
3896 && ipa_get_jf_pass_through_formal_id (jfunc) == i) | |
3897 return true; | |
3898 return false; | |
3899 } | |
3900 | |
3845 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in | 3901 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in |
3846 KNOWN_CSTS with constants that are also known for all of the CALLERS. */ | 3902 KNOWN_CSTS with constants that are also known for all of the CALLERS. */ |
3847 | 3903 |
3848 static void | 3904 static void |
3849 find_more_scalar_values_for_callers_subset (struct cgraph_node *node, | 3905 find_more_scalar_values_for_callers_subset (struct cgraph_node *node, |
3857 { | 3913 { |
3858 struct cgraph_edge *cs; | 3914 struct cgraph_edge *cs; |
3859 tree newval = NULL_TREE; | 3915 tree newval = NULL_TREE; |
3860 int j; | 3916 int j; |
3861 bool first = true; | 3917 bool first = true; |
3918 tree type = ipa_get_type (info, i); | |
3862 | 3919 |
3863 if (ipa_get_scalar_lat (info, i)->bottom || known_csts[i]) | 3920 if (ipa_get_scalar_lat (info, i)->bottom || known_csts[i]) |
3864 continue; | 3921 continue; |
3865 | 3922 |
3866 FOR_EACH_VEC_ELT (callers, j, cs) | 3923 FOR_EACH_VEC_ELT (callers, j, cs) |
3867 { | 3924 { |
3868 struct ipa_jump_func *jump_func; | 3925 struct ipa_jump_func *jump_func; |
3869 tree t; | 3926 tree t; |
3870 | 3927 |
3928 if (IPA_NODE_REF (cs->caller)->node_dead) | |
3929 continue; | |
3930 | |
3871 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)) | 3931 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)) |
3872 || (i == 0 | 3932 || (i == 0 |
3873 && call_passes_through_thunk_p (cs)) | 3933 && call_passes_through_thunk_p (cs))) |
3874 || (!cs->callee->instrumentation_clone | |
3875 && cs->callee->function_symbol ()->instrumentation_clone)) | |
3876 { | 3934 { |
3877 newval = NULL_TREE; | 3935 newval = NULL_TREE; |
3878 break; | 3936 break; |
3879 } | 3937 } |
3880 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i); | 3938 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i); |
3881 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func); | 3939 if (self_recursive_pass_through_p (cs, jump_func, i)) |
3940 continue; | |
3941 | |
3942 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func, type); | |
3882 if (!t | 3943 if (!t |
3883 || (newval | 3944 || (newval |
3884 && !values_equal_for_ipcp_p (t, newval)) | 3945 && !values_equal_for_ipcp_p (t, newval)) |
3885 || (!first && !newval)) | 3946 || (!first && !newval)) |
3886 { | 3947 { |
4025 if (aglat->offset - offset > item->offset) | 4086 if (aglat->offset - offset > item->offset) |
4026 break; | 4087 break; |
4027 if (aglat->offset - offset == item->offset) | 4088 if (aglat->offset - offset == item->offset) |
4028 { | 4089 { |
4029 gcc_checking_assert (item->value); | 4090 gcc_checking_assert (item->value); |
4030 if (values_equal_for_ipcp_p (item->value, aglat->values->value)) | 4091 if (aglat->is_single_const () |
4092 && values_equal_for_ipcp_p (item->value, | |
4093 aglat->values->value)) | |
4031 found = true; | 4094 found = true; |
4032 break; | 4095 break; |
4033 } | 4096 } |
4034 aglat = aglat->next; | 4097 aglat = aglat->next; |
4035 } | 4098 } |
4178 intersect_with_agg_replacements (cs->caller, src_idx, &inter, | 4241 intersect_with_agg_replacements (cs->caller, src_idx, &inter, |
4179 delta); | 4242 delta); |
4180 } | 4243 } |
4181 else | 4244 else |
4182 { | 4245 { |
4183 src_plats = ipa_get_parm_lattices (caller_info, src_idx);; | 4246 src_plats = ipa_get_parm_lattices (caller_info, src_idx); |
4184 /* Currently we do not produce clobber aggregate jump | 4247 /* Currently we do not produce clobber aggregate jump |
4185 functions, adjust when we do. */ | 4248 functions, adjust when we do. */ |
4186 gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items); | 4249 gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items); |
4187 if (!inter.exists ()) | 4250 if (!inter.exists ()) |
4188 inter = copy_plats_to_inter (src_plats, delta); | 4251 inter = copy_plats_to_inter (src_plats, delta); |
4200 inter.safe_push ((*jfunc->agg.items)[i]); | 4263 inter.safe_push ((*jfunc->agg.items)[i]); |
4201 else | 4264 else |
4202 FOR_EACH_VEC_ELT (inter, k, item) | 4265 FOR_EACH_VEC_ELT (inter, k, item) |
4203 { | 4266 { |
4204 int l = 0; | 4267 int l = 0; |
4205 bool found = false;; | 4268 bool found = false; |
4206 | 4269 |
4207 if (!item->value) | 4270 if (!item->value) |
4208 continue; | 4271 continue; |
4209 | 4272 |
4210 while ((unsigned) l < jfunc->agg.items->length ()) | 4273 while ((unsigned) l < jfunc->agg.items->length ()) |
4268 if (plats->aggs_bottom) | 4331 if (plats->aggs_bottom) |
4269 continue; | 4332 continue; |
4270 | 4333 |
4271 FOR_EACH_VEC_ELT (callers, j, cs) | 4334 FOR_EACH_VEC_ELT (callers, j, cs) |
4272 { | 4335 { |
4336 struct ipa_jump_func *jfunc | |
4337 = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i); | |
4338 if (self_recursive_pass_through_p (cs, jfunc, i) | |
4339 && (!plats->aggs_by_ref | |
4340 || ipa_get_jf_pass_through_agg_preserved (jfunc))) | |
4341 continue; | |
4273 inter = intersect_aggregates_with_edge (cs, i, inter); | 4342 inter = intersect_aggregates_with_edge (cs, i, inter); |
4274 | 4343 |
4275 if (!inter.exists ()) | 4344 if (!inter.exists ()) |
4276 goto next_param; | 4345 goto next_param; |
4277 } | 4346 } |
4298 } | 4367 } |
4299 *tail = NULL; | 4368 *tail = NULL; |
4300 return res; | 4369 return res; |
4301 } | 4370 } |
4302 | 4371 |
4303 /* Turn KNOWN_AGGS into a list of aggregate replacement values. */ | |
4304 | |
4305 static struct ipa_agg_replacement_value * | |
4306 known_aggs_to_agg_replacement_list (vec<ipa_agg_jump_function> known_aggs) | |
4307 { | |
4308 struct ipa_agg_replacement_value *res; | |
4309 struct ipa_agg_replacement_value **tail = &res; | |
4310 struct ipa_agg_jump_function *aggjf; | |
4311 struct ipa_agg_jf_item *item; | |
4312 int i, j; | |
4313 | |
4314 FOR_EACH_VEC_ELT (known_aggs, i, aggjf) | |
4315 FOR_EACH_VEC_SAFE_ELT (aggjf->items, j, item) | |
4316 { | |
4317 struct ipa_agg_replacement_value *v; | |
4318 v = ggc_alloc<ipa_agg_replacement_value> (); | |
4319 v->index = i; | |
4320 v->offset = item->offset; | |
4321 v->value = item->value; | |
4322 v->by_ref = aggjf->by_ref; | |
4323 *tail = v; | |
4324 tail = &v->next; | |
4325 } | |
4326 *tail = NULL; | |
4327 return res; | |
4328 } | |
4329 | |
4330 /* Determine whether CS also brings all scalar values that the NODE is | 4372 /* Determine whether CS also brings all scalar values that the NODE is |
4331 specialized for. */ | 4373 specialized for. */ |
4332 | 4374 |
4333 static bool | 4375 static bool |
4334 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs, | 4376 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs, |
4352 continue; | 4394 continue; |
4353 | 4395 |
4354 if (i >= ipa_get_cs_argument_count (args)) | 4396 if (i >= ipa_get_cs_argument_count (args)) |
4355 return false; | 4397 return false; |
4356 jump_func = ipa_get_ith_jump_func (args, i); | 4398 jump_func = ipa_get_ith_jump_func (args, i); |
4357 t = ipa_value_from_jfunc (caller_info, jump_func); | 4399 t = ipa_value_from_jfunc (caller_info, jump_func, |
4400 ipa_get_type (dest_info, i)); | |
4358 if (!t || !values_equal_for_ipcp_p (val, t)) | 4401 if (!t || !values_equal_for_ipcp_p (val, t)) |
4359 return false; | 4402 return false; |
4360 } | 4403 } |
4361 return true; | 4404 return true; |
4362 } | 4405 } |
4449 for (src = val->sources; src; src = src->next) | 4492 for (src = val->sources; src; src = src->next) |
4450 { | 4493 { |
4451 struct cgraph_edge *cs = src->cs; | 4494 struct cgraph_edge *cs = src->cs; |
4452 while (cs) | 4495 while (cs) |
4453 { | 4496 { |
4454 if (cgraph_edge_brings_value_p (cs, src, node) | 4497 if (cgraph_edge_brings_value_p (cs, src, node, val) |
4455 && cgraph_edge_brings_all_scalars_for_node (cs, val->spec_node) | 4498 && cgraph_edge_brings_all_scalars_for_node (cs, val->spec_node) |
4456 && cgraph_edge_brings_all_agg_vals_for_node (cs, val->spec_node)) | 4499 && cgraph_edge_brings_all_agg_vals_for_node (cs, val->spec_node)) |
4457 { | 4500 { |
4458 if (dump_file) | 4501 if (dump_file) |
4459 fprintf (dump_file, " - adding an extra caller %s of %s\n", | 4502 fprintf (dump_file, " - adding an extra caller %s of %s\n", |
4460 cs->caller->dump_name (), | 4503 cs->caller->dump_name (), |
4461 val->spec_node->dump_name ()); | 4504 val->spec_node->dump_name ()); |
4462 | 4505 |
4463 cs->redirect_callee_duplicating_thunks (val->spec_node); | 4506 cs->redirect_callee_duplicating_thunks (val->spec_node); |
4464 val->spec_node->expand_all_artificial_thunks (); | 4507 val->spec_node->expand_all_artificial_thunks (); |
4465 if (cs->count.initialized_p ()) | 4508 if (cs->count.ipa ().initialized_p ()) |
4466 redirected_sum = redirected_sum + cs->count; | 4509 redirected_sum = redirected_sum + cs->count.ipa (); |
4467 } | 4510 } |
4468 cs = get_next_cgraph_edge_clone (cs); | 4511 cs = get_next_cgraph_edge_clone (cs); |
4469 } | 4512 } |
4470 } | 4513 } |
4471 | 4514 |
4472 if (redirected_sum > profile_count::zero ()) | 4515 if (redirected_sum.nonzero_p ()) |
4473 update_specialized_profile (val->spec_node, node, redirected_sum); | 4516 update_specialized_profile (val->spec_node, node, redirected_sum); |
4474 } | 4517 } |
4475 | 4518 |
4476 /* Return true if KNOWN_CONTEXTS contain at least one useful context. */ | 4519 /* Return true if KNOWN_CONTEXTS contain at least one useful context. */ |
4477 | 4520 |
4714 if (dump_file) | 4757 if (dump_file) |
4715 fprintf (dump_file, " - Creating a specialized node of %s " | 4758 fprintf (dump_file, " - Creating a specialized node of %s " |
4716 "for all known contexts.\n", node->dump_name ()); | 4759 "for all known contexts.\n", node->dump_name ()); |
4717 | 4760 |
4718 callers = node->collect_callers (); | 4761 callers = node->collect_callers (); |
4762 find_more_scalar_values_for_callers_subset (node, known_csts, callers); | |
4763 find_more_contexts_for_caller_subset (node, &known_contexts, callers); | |
4764 ipa_agg_replacement_value *aggvals | |
4765 = find_aggregate_values_for_callers_subset (node, callers); | |
4719 | 4766 |
4720 if (!known_contexts_useful_p (known_contexts)) | 4767 if (!known_contexts_useful_p (known_contexts)) |
4721 { | 4768 { |
4722 known_contexts.release (); | 4769 known_contexts.release (); |
4723 known_contexts = vNULL; | 4770 known_contexts = vNULL; |
4724 } | 4771 } |
4725 clone = create_specialized_node (node, known_csts, known_contexts, | 4772 clone = create_specialized_node (node, known_csts, known_contexts, |
4726 known_aggs_to_agg_replacement_list (known_aggs), | 4773 aggvals, callers); |
4727 callers); | |
4728 info = IPA_NODE_REF (node); | 4774 info = IPA_NODE_REF (node); |
4729 info->do_clone_for_all_contexts = false; | 4775 info->do_clone_for_all_contexts = false; |
4730 IPA_NODE_REF (clone)->is_all_contexts_clone = true; | 4776 IPA_NODE_REF (clone)->is_all_contexts_clone = true; |
4731 for (i = 0; i < count; i++) | 4777 for (i = 0; i < count; i++) |
4732 vec_free (known_aggs[i].items); | 4778 vec_free (known_aggs[i].items); |
4882 } | 4928 } |
4883 | 4929 |
4884 if (!found_useful_result) | 4930 if (!found_useful_result) |
4885 continue; | 4931 continue; |
4886 | 4932 |
4887 ipcp_grow_transformations_if_necessary (); | 4933 ipcp_transformation_initialize (); |
4888 ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node); | 4934 ipcp_transformation *ts = ipcp_transformation_sum->get_create (node); |
4889 vec_safe_reserve_exact (ts->bits, count); | 4935 vec_safe_reserve_exact (ts->bits, count); |
4890 | 4936 |
4891 for (unsigned i = 0; i < count; i++) | 4937 for (unsigned i = 0; i < count; i++) |
4892 { | 4938 { |
4893 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | 4939 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); |
4955 } | 5001 } |
4956 } | 5002 } |
4957 if (!found_useful_result) | 5003 if (!found_useful_result) |
4958 continue; | 5004 continue; |
4959 | 5005 |
4960 ipcp_grow_transformations_if_necessary (); | 5006 ipcp_transformation_initialize (); |
4961 ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node); | 5007 ipcp_transformation *ts = ipcp_transformation_sum->get_create (node); |
4962 vec_safe_reserve_exact (ts->m_vr, count); | 5008 vec_safe_reserve_exact (ts->m_vr, count); |
4963 | 5009 |
4964 for (unsigned i = 0; i < count; i++) | 5010 for (unsigned i = 0; i < count; i++) |
4965 { | 5011 { |
4966 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); | 5012 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); |
4968 | 5014 |
4969 if (!plats->m_value_range.bottom_p () | 5015 if (!plats->m_value_range.bottom_p () |
4970 && !plats->m_value_range.top_p ()) | 5016 && !plats->m_value_range.top_p ()) |
4971 { | 5017 { |
4972 vr.known = true; | 5018 vr.known = true; |
4973 vr.type = plats->m_value_range.m_vr.type; | 5019 vr.type = plats->m_value_range.m_vr.kind (); |
4974 vr.min = wi::to_wide (plats->m_value_range.m_vr.min); | 5020 vr.min = wi::to_wide (plats->m_value_range.m_vr.min ()); |
4975 vr.max = wi::to_wide (plats->m_value_range.m_vr.max); | 5021 vr.max = wi::to_wide (plats->m_value_range.m_vr.max ()); |
4976 } | 5022 } |
4977 else | 5023 else |
4978 { | 5024 { |
4979 vr.known = false; | 5025 vr.known = false; |
4980 vr.type = VR_VARYING; | 5026 vr.type = VR_VARYING; |
4988 /* The IPCP driver. */ | 5034 /* The IPCP driver. */ |
4989 | 5035 |
4990 static unsigned int | 5036 static unsigned int |
4991 ipcp_driver (void) | 5037 ipcp_driver (void) |
4992 { | 5038 { |
4993 struct cgraph_2edge_hook_list *edge_duplication_hook_holder; | |
4994 struct cgraph_edge_hook_list *edge_removal_hook_holder; | |
4995 struct ipa_topo_info topo; | 5039 struct ipa_topo_info topo; |
5040 | |
5041 if (edge_clone_summaries == NULL) | |
5042 edge_clone_summaries = new edge_clone_summary_t (symtab); | |
4996 | 5043 |
4997 ipa_check_create_node_params (); | 5044 ipa_check_create_node_params (); |
4998 ipa_check_create_edge_args (); | 5045 ipa_check_create_edge_args (); |
4999 grow_edge_clone_vectors (); | |
5000 edge_duplication_hook_holder | |
5001 = symtab->add_edge_duplication_hook (&ipcp_edge_duplication_hook, NULL); | |
5002 edge_removal_hook_holder | |
5003 = symtab->add_edge_removal_hook (&ipcp_edge_removal_hook, NULL); | |
5004 | 5046 |
5005 if (dump_file) | 5047 if (dump_file) |
5006 { | 5048 { |
5007 fprintf (dump_file, "\nIPA structures before propagation:\n"); | 5049 fprintf (dump_file, "\nIPA structures before propagation:\n"); |
5008 if (dump_flags & TDF_DETAILS) | 5050 if (dump_flags & TDF_DETAILS) |
5021 /* Store results of value range propagation. */ | 5063 /* Store results of value range propagation. */ |
5022 ipcp_store_vr_results (); | 5064 ipcp_store_vr_results (); |
5023 | 5065 |
5024 /* Free all IPCP structures. */ | 5066 /* Free all IPCP structures. */ |
5025 free_toporder_info (&topo); | 5067 free_toporder_info (&topo); |
5026 next_edge_clone.release (); | 5068 delete edge_clone_summaries; |
5027 prev_edge_clone.release (); | 5069 edge_clone_summaries = NULL; |
5028 symtab->remove_edge_removal_hook (edge_removal_hook_holder); | |
5029 symtab->remove_edge_duplication_hook (edge_duplication_hook_holder); | |
5030 ipa_free_all_structures_after_ipa_cp (); | 5070 ipa_free_all_structures_after_ipa_cp (); |
5031 if (dump_file) | 5071 if (dump_file) |
5032 fprintf (dump_file, "\nIPA constant propagation end\n"); | 5072 fprintf (dump_file, "\nIPA constant propagation end\n"); |
5033 return 0; | 5073 return 0; |
5034 } | 5074 } |
5123 within the same process. For use by toplev::finalize. */ | 5163 within the same process. For use by toplev::finalize. */ |
5124 | 5164 |
5125 void | 5165 void |
5126 ipa_cp_c_finalize (void) | 5166 ipa_cp_c_finalize (void) |
5127 { | 5167 { |
5128 max_count = profile_count::zero (); | 5168 max_count = profile_count::uninitialized (); |
5129 overall_size = 0; | 5169 overall_size = 0; |
5130 max_new_size = 0; | 5170 max_new_size = 0; |
5131 } | 5171 } |