diff options
author | Erick Ochoa <erick.ochoa@theobroma-systems.com> | 2020-03-10 10:26:58 +0100 |
---|---|---|
committer | Erick Ochoa <erick.ochoa@theobroma-systems.com> | 2020-04-28 23:35:49 +0200 |
commit | 4d2dbb54bd00a4d32c417afbb86c73ff10be1d54 (patch) | |
tree | 0c67e684f3bcfff7b7162045e81d5c304523374b | |
parent | 4e178ad5cfa6c2e23b81537838458650251d435d (diff) |
wip
-rw-r--r-- | gcc/ipa-hello-world.c | 163 |
1 files changed, 126 insertions, 37 deletions
diff --git a/gcc/ipa-hello-world.c b/gcc/ipa-hello-world.c index 8289728f9bc..6d902a03ecf 100644 --- a/gcc/ipa-hello-world.c +++ b/gcc/ipa-hello-world.c @@ -27,6 +27,7 @@ #include "gimple.h" #include "cfg.h" // needed for gimple-iterator.h #include "gimple-iterator.h" +#include <stdbool.h> #include "ipa-str-reorg-utils.h" @@ -43,15 +44,53 @@ log (const char * const format, ...) } -struct escaping_info_s { const_tree type; bool is_escaping; }; +struct escaping_reason_s { + unsigned global_is_visible : 1; + unsigned parameter_is_visible : 1; + unsigned return_is_visible : 1; + unsigned type_is_casted : 1; +}; +typedef struct escaping_reason_s escaping_reason; + +struct escaping_info_s { const_tree type; bool is_escaping; escaping_reason reason; }; typedef struct escaping_info_s escaping_info; typedef hash_map<const_tree, escaping_info> type_map; static bool filter_type (type_map &escape_map, const_tree type); -void update_escape_info (const_tree type, type_map &escape_map, bool is_escaping); +void update_escape_info (const_tree type, type_map &escape_map, bool is_escaping, escaping_reason reason); + +static const escaping_reason null_reason = { 0, 0, 0, 0 }; +inline escaping_reason +new_escaping_reason() +{ + return null_reason; +} + +//TODO: +// Should we be using C++? +escaping_reason +union_op(const escaping_reason &left, const escaping_reason &right) +{ + escaping_reason retval; + retval.global_is_visible = left.global_is_visible | right.global_is_visible; + retval.parameter_is_visible = left.parameter_is_visible | right.parameter_is_visible; + retval.return_is_visible = left.return_is_visible | right.return_is_visible;; + retval.type_is_casted = left.type_is_casted | right.type_is_casted;; + return retval; +} + +void +explain_print(escaping_reason reason) +{ + if (reason.global_is_visible) log("global is visible"); + if (reason.parameter_is_visible) log(", parameter is visible"); + if (reason.return_is_visible) log(", return is visible"); + if (reason.type_is_casted) log(", type is casted"); + log("\n"); +} void -update_escape_info_pointer (const_tree pointer_type, type_map &escape_map, bool is_escaping) +update_escape_info_pointer (const_tree pointer_type, type_map &escape_map, bool is_escaping, escaping_reason reason) { gcc_assert(pointer_type); enum tree_code tree_code_pointer_type = TREE_CODE(pointer_type); @@ -62,13 +101,14 @@ update_escape_info_pointer (const_tree pointer_type, type_map &escape_map, bool if (!info) return; info->is_escaping |= is_escaping; + info->reason = union_op(info->reason, reason); tree tree_type_pointer_type = TREE_TYPE(pointer_type); gcc_assert(tree_type_pointer_type); - update_escape_info (tree_type_pointer_type, escape_map, info->is_escaping); + update_escape_info (tree_type_pointer_type, escape_map, info->is_escaping, info->reason); } void -update_escape_info_array (const_tree array_type, type_map &escape_map, bool is_escaping) +update_escape_info_array (const_tree array_type, type_map &escape_map, bool is_escaping, escaping_reason reason) { gcc_assert(array_type); enum tree_code tree_code_array_type = TREE_CODE(array_type); @@ -79,13 +119,14 @@ update_escape_info_array (const_tree array_type, type_map &escape_map, bool is_e if (!info) return; info->is_escaping |= is_escaping; + info->reason = union_op(info->reason, reason); tree tree_type_array_type = TREE_TYPE(array_type); gcc_assert(tree_type_array_type); - update_escape_info (tree_type_array_type, escape_map, info->is_escaping); + update_escape_info (tree_type_array_type, escape_map, info->is_escaping, info->reason); } void -update_escape_info_record (const_tree record_type, type_map &escape_map, bool is_escaping) +update_escape_info_record (const_tree record_type, type_map &escape_map, bool is_escaping, escaping_reason reason) { gcc_assert(record_type); enum tree_code tree_code_record_type = TREE_CODE(record_type); @@ -97,6 +138,7 @@ update_escape_info_record (const_tree record_type, type_map &escape_map, bool is // it in the escaping info gcc_assert(info); info->is_escaping |= is_escaping; + info->reason = union_op(info->reason, reason); for (tree field = TYPE_FIELDS (record_type); field; field = DECL_CHAIN (field)) @@ -104,28 +146,30 @@ update_escape_info_record (const_tree record_type, type_map &escape_map, bool is gcc_assert(field); tree tree_type_field = TREE_TYPE(field); gcc_assert(tree_type_field); - update_escape_info (tree_type_field, escape_map, info->is_escaping); + update_escape_info (tree_type_field, escape_map, info->is_escaping, info->reason); } } void -update_escape_info (const_tree type, type_map &escape_map, bool is_escaping) +update_escape_info (const_tree type, type_map &escape_map, bool is_escaping, escaping_reason reason) { // INFO: This is an optimization. if (!is_escaping) return; gcc_assert(type); enum tree_code tree_code_type = TREE_CODE(type); + // We need to make sure that we are only dealing with + // the main type and not typedefs... switch (tree_code_type) { case ARRAY_TYPE: - update_escape_info_array(type, escape_map, is_escaping); + update_escape_info_array(type, escape_map, is_escaping, reason); break; case POINTER_TYPE: - update_escape_info_pointer(type, escape_map, is_escaping); + update_escape_info_pointer(type, escape_map, is_escaping, reason); break; case RECORD_TYPE: - update_escape_info_record(type, escape_map, is_escaping); + update_escape_info_record(type, escape_map, is_escaping, reason); break; default: break; @@ -187,7 +231,8 @@ filter_type (type_map &escape_map, const_tree type) if (retval) return retval; - escaping_info info = { type, false }; + escaping_reason reason = new_escaping_reason(); + escaping_info info = { type , false , reason}; escape_map.put(type, info); return retval; } @@ -234,7 +279,8 @@ collect_global(type_map &escape_map, varpool_node *vnode) tree type = TREE_TYPE(decl); gcc_assert(type); - escaping_info info = { type, false }; + escaping_reason reason = new_escaping_reason(); + escaping_info info = { type, false, reason }; escape_map.put (type, info); } } @@ -263,7 +309,9 @@ collect_parm_declarations (cgraph_node *cnode, type_map &escape_map) log("putting parameter type %s\n", get_type_name(type)); gcc_assert(type); - escaping_info info = { type, false }; + + escaping_reason reason = new_escaping_reason(); + escaping_info info = { type, false, reason }; escape_map.put(type, info); } } @@ -284,7 +332,8 @@ collect_local_declarations (cgraph_node *cnode, type_map &escape_map) tree tree_type = TREE_TYPE(var_decl); gcc_assert(tree_type); - escaping_info info = { tree_type, false }; + escaping_reason reason = new_escaping_reason(); + escaping_info info = { tree_type, false, reason}; escape_map.put(tree_type, info); } } @@ -296,22 +345,25 @@ collect_pointer_plus (tree lhs, tree rhs1, tree rhs2, type_map &escape_map) bool is_lhs_boring = lhs_type ? filter_type(escape_map, lhs_type) : true; const_tree rhs1_type = rhs1 ? TREE_TYPE(rhs1) : NULL; bool is_rhs1_boring = rhs1_type ? filter_type(escape_map, rhs1_type) : true; - const_tree rhs2_type = rhs2 ? TREE_TYPE(rhs2): NULL; + const_tree rhs2_type = rhs2 ? TREE_TYPE(rhs2) : NULL; bool is_rhs2_boring = rhs2_type ? filter_type(escape_map, rhs2_type) : true; if (!is_lhs_boring) { - escaping_info info = { lhs_type , false }; + escaping_reason reason = new_escaping_reason(); + escaping_info info = { lhs_type , false, reason }; escape_map.put(lhs_type, info); } if (!is_rhs1_boring) { - escaping_info info = { rhs1_type, false }; + escaping_reason reason = new_escaping_reason(); + escaping_info info = { rhs1_type, false , reason}; escape_map.put(rhs1_type, info); } if (!is_rhs2_boring) { - escaping_info info = {rhs2_type, false}; + escaping_reason reason = new_escaping_reason(); + escaping_info info = {rhs2_type, false, reason}; escape_map.put(rhs2_type, info); } } @@ -410,7 +462,8 @@ _print_types( const_tree const &type, escaping_info *info, __attribute((unused)) { log("collected,%s\n", get_type_name(type)); bool is_escaping = info->is_escaping; - log("type %s is escaping %s\n", get_type_name(type), is_escaping ? "true" : "false"); + log("type %s is escaping %s : ", get_type_name(type), is_escaping ? "true" : "false"); + explain_print(info->reason); return true; } @@ -429,14 +482,14 @@ is_variable_escaping(varpool_node *vnode) } static bool -is_function_escaping(cgraph_node *cnode) +is_function_escaping(const cgraph_node *cnode) { gcc_assert(cnode); return cnode->externally_visible; } void -calculate_escaping_parameters(cgraph_node *cnode, type_map &escape_map) +calculate_escaping_parameters(const cgraph_node *cnode, type_map &escape_map) { gcc_assert(cnode); tree function = cnode->decl; @@ -455,13 +508,16 @@ calculate_escaping_parameters(cgraph_node *cnode, type_map &escape_map) tree tree_type = TREE_TYPE(parm); gcc_assert(tree_type); // void update_escaping_info (const_tree type, type_map &escape_map, bool is_escaping); - update_escape_info(tree_type, escape_map, is_escaping); + + escaping_reason reason = new_escaping_reason(); + reason.parameter_is_visible = is_escaping; + update_escape_info(tree_type, escape_map, is_escaping, reason); log("variable %s is escaping %s\n", identifier, is_escaping ? "true" : "false"); } } void -is_return_type_escaping(cgraph_node *cnode, type_map &escape_map) +is_return_type_escaping(const cgraph_node *cnode, type_map &escape_map) { gcc_assert(cnode); bool is_escaping = is_function_escaping(cnode); @@ -478,26 +534,55 @@ is_return_type_escaping(cgraph_node *cnode, type_map &escape_map) log("return type %s\n", get_type_name(return_type)); // void update_escaping_info (const_tree type, type_map &escape_map, bool is_escaping); - update_escape_info(return_type, escape_map, is_escaping); +/*struct escaping_reason_s { + unsigned global_is_visible : 1; + unsigned function_is_visible : 1; +}; +*/ + escaping_reason reason = new_escaping_reason(); + reason.return_is_visible = is_escaping; + update_escape_info(return_type, escape_map, is_escaping, reason); //escaping_info *info = escape_map.get(return_type); // If there's no info it means it is not interesting... //if (!info) return; //info->is_escaping |= is_escaping; } + +bool +calculate_escaping_types_from_function_signatures ( + cgraph_node * const &cnode, type_map *escape_map) +{ + + gcc_assert(escape_map); + gcc_assert(cnode); + bool is_escaping = is_function_escaping(cnode); + log("function %s is escaping %s\n", cnode->name(), is_escaping ? "true" : "false"); + calculate_escaping_parameters(cnode, *escape_map); + is_return_type_escaping(cnode, *escape_map); + return true; +} + void is_any_function_escaping(type_map &escape_map) { cgraph_node *cnode = NULL; + hash_set<cgraph_node *> not_defined_functions; + FOR_EACH_FUNCTION (cnode) { - cnode->get_untransformed_body(); - log("function name = %s\n", cnode->name()); - bool is_escaping = is_function_escaping(cnode); - log("function %s is escaping %s\n", cnode->name(), is_escaping ? "true" : "false"); - calculate_escaping_parameters(cnode, escape_map); - is_return_type_escaping(cnode, escape_map); + gcc_assert(cnode); + not_defined_functions.add(cnode); + } + + FOR_EACH_DEFINED_FUNCTION(cnode) + { + gcc_assert(cnode); + cnode->get_untransformed_body(); + not_defined_functions.remove(cnode); } + + not_defined_functions.traverse<type_map *, calculate_escaping_types_from_function_signatures> (&escape_map); } void @@ -514,7 +599,9 @@ is_any_variable_escaping(type_map &escape_map) tree type = TREE_TYPE(decl); gcc_assert(type); // void update_escaping_info (const_tree type, type_map &escape_map, bool is_escaping); - update_escape_info (type, escape_map, is_escaping); + escaping_reason reason = new_escaping_reason(); + reason.global_is_visible = is_escaping; + update_escape_info (type, escape_map, is_escaping, reason); //escaping_info *info = escape_map.get(type); //if (!info) return; //info->is_escaping |= is_escaping; @@ -549,15 +636,17 @@ cast_to_void_in_assign(const_tree lhs, const_tree rhs, type_map &escape_map) log("lhs = %s, rhs = %s\n", type_name_lhs, type_name_rhs); if (!is_var_decl_or_ssa_name) return; - bool is_casting_stmt = tree_type_lhs != tree_type_rhs; + bool is_casting_stmt = TYPE_MAIN_VARIANT(tree_type_lhs) != TYPE_MAIN_VARIANT(tree_type_rhs); log("is casting stmt ? %s\n", is_casting_stmt ? "true" : "false"); if (!is_casting_stmt) return; log("escaping lhs %s\n", type_name_lhs); - update_escape_info(tree_type_lhs, escape_map, true); + escaping_reason reason = new_escaping_reason(); + reason.type_is_casted = is_casting_stmt; + update_escape_info(tree_type_lhs, escape_map, is_casting_stmt, reason); log("escaping rhs %s\n", type_name_rhs); - update_escape_info(tree_type_rhs, escape_map, true); + update_escape_info(tree_type_rhs, escape_map, is_casting_stmt, reason); } static void @@ -632,7 +721,7 @@ static void cast_to_void_in_program(type_map &escape_map) { cgraph_node *cnode = NULL; - FOR_EACH_FUNCTION (cnode) + FOR_EACH_DEFINED_FUNCTION (cnode) { gcc_assert(cnode); cnode->get_untransformed_body(); |