diff options
Diffstat (limited to 'gcc/ipa-hello-world.c')
-rw-r--r-- | gcc/ipa-hello-world.c | 151 |
1 files changed, 132 insertions, 19 deletions
diff --git a/gcc/ipa-hello-world.c b/gcc/ipa-hello-world.c index 9040a9360a6..cb69b1ea713 100644 --- a/gcc/ipa-hello-world.c +++ b/gcc/ipa-hello-world.c @@ -21,29 +21,142 @@ #include "tree-ssa-ccp.h" #include "stringpool.h" #include "attribs.h" +#include "tree-cfg.h" +#include <map> +#include <set> -static unsigned int -iphw_execute() +#include "ipa-type-escape-analysis.h" + + +//TODO: place in header file +inline static void +print_function (cgraph_node *cnode) +{ + if (!dump_file) + return; + gcc_assert (cnode); + cnode->get_untransformed_body (); + dump_function_to_file (cnode->decl, dump_file, TDF_NONE); +} + +typedef std::pair<const_tree /* record */, const_tree /* field */> fields; +typedef std::pair<unsigned /* reads */, unsigned /* writes */> accesses; +struct field_comparator +{ + bool operator()(const fields &left, const fields &right) const + { + const_tree left_record = left.first; + gcc_assert(left_record); + const_tree right_record = right.first; + gcc_assert(right_record); + // Make sure that we are only comparing valid types... + const enum tree_code tree_code_left_record = TREE_CODE(left_record); + const enum tree_code tree_code_right_record = TREE_CODE(right_record); + const bool is_left_record_type = RECORD_TYPE == tree_code_left_record; + const bool is_right_record_type = RECORD_TYPE == tree_code_right_record; + const bool are_left_and_right_valid = is_left_record_type && is_right_record_type; + gcc_assert(are_left_and_right_valid); + + // Handle typedefs: + // Get the main variants of the main types + const_tree main_variant_left = TYPE_MAIN_VARIANT(left_record); + gcc_assert(main_variant_left); + const_tree main_variant_right = TYPE_MAIN_VARIANT(right_record); + gcc_assert(main_variant_right); + // If they are not equal, we can do a comparison of the types here... + const bool are_main_variants_equal = main_variant_left == main_variant_right; + const bool left_type_less_than_right_type = main_variant_left < main_variant_right; + if (!are_main_variants_equal) return left_type_less_than_right_type; + + // If they are equal, that means that we are comparing fields defined in the same record + const_tree left_field = left.second; + gcc_assert(left_field); + const_tree right_field = right.second; + gcc_assert(right_field); + // Make sure that they are valid + const enum tree_code tree_code_left_field = TREE_CODE(left_field); + const enum tree_code tree_code_right_field = TREE_CODE(right_field); + const bool is_left_field_field_decl = FIELD_DECL == tree_code_left_field; + const bool is_right_field_field_decl = FIELD_DECL == tree_code_right_field; + const bool are_left_and_right_field_decls = is_left_field_field_decl && is_right_field_field_decl; + gcc_assert(are_left_and_right_field_decls); + + // Compare on the field offset. + const_tree left_constant = byte_position(left_field); + gcc_assert(left_constant); + const_tree right_constant = byte_position(right_field); + gcc_assert(right_constant); + unsigned left_offset = tree_to_uhwi(left_constant); + unsigned right_offset = tree_to_uhwi(right_constant); + const bool left_offset_less_than_right_offset = left_offset < right_offset; + return left_offset_less_than_right_offset; + } +}; + +typedef std::map<fields, accesses, field_comparator> field_access_counter; +typedef std::set<const_tree> record_set; + +/* INFO: + * Yes, I know we are returning a std::map. + * Bad pattern? Maybe, but this will only be called once + * and I rather pass by value because that allows + * me to have a pure function and not worry about + * garbage collection + * + * TODO: I'd like to change type_map for a std::map + * TODO: I'd like to make this a template that can work + * for std::map and std::set + */ +field_access_counter +count_access_for_types(record_set &non_escaping_records) { - cgraph_node *node; - FOR_EACH_FUNCTION(node) + field_access_counter counter; + cgraph_node *cnode = NULL; + FOR_EACH_DEFINED_FUNCTION(cnode) { - if (dump_file) fprintf(dump_file, "the name of the function is %s\n", node->dump_asm_name()); - - if (strcmp(node->dump_asm_name(), "bar/49") != 0) continue; - - node->get_untransformed_body(); - fprintf(dump_file, "we are where we need to be\n"); - cgraph_node *clone = node->create_version_clone_with_body( - node->collect_callers(), - NULL, - NULL, - NULL, - NULL, - "helloworld", - NULL); + gcc_assert(cnode); + print_function(cnode); } + return counter; +} + +bool +_calculate_non_escaping_records(const_tree const &type, escaping_info *info, record_set *non_escaping_records) +{ + gcc_assert(info); + gcc_assert(non_escaping_records); + + enum tree_code tree_code_type = TREE_CODE(type); + const bool is_record_type = RECORD_TYPE == tree_code_type; + if (!is_record_type) return true; + + non_escaping_records->insert(type); + return true; +} + +/* + * Yes, again, we are passing a std::set + * as a value. I don\t care too much since + * this is only called once... + */ +static record_set +calculate_non_escaping_records(type_map &escaping_type_info) +{ + // We are going to have to traverse the type_map... + // This is why I don't really like hash_set... + record_set non_escaping_records; + escaping_type_info.traverse<record_set*, _calculate_non_escaping_records>(&non_escaping_records); + return non_escaping_records; +} + +static unsigned int +iphw_execute() +{ + type_map escaping_types; + calculate_escaping_types(escaping_types); + record_set non_escaping_records = calculate_non_escaping_records(escaping_types); + field_access_counter counter = count_access_for_types(non_escaping_records); return 0; } @@ -51,7 +164,7 @@ namespace { const pass_data pass_data_ipa_hello_world = { SIMPLE_IPA_PASS, - "hello_world", + "hello-world", OPTGROUP_NONE, TV_NONE, (PROP_cfg | PROP_ssa), |