diff options
author | Erick Ochoa <erick.ochoa@theobroma-systems.com> | 2020-03-10 16:30:54 +0100 |
---|---|---|
committer | Erick Ochoa <erick.ochoa@theobroma-systems.com> | 2020-06-03 16:05:21 +0200 |
commit | 136f2749fd3ac846a8e5be2cbbf32abdb7b9e179 (patch) | |
tree | 2d4b4d1863d8c85fa70df22305379c96581ddbb1 | |
parent | e4389908cc090e769b94051c7ddef4136565173c (diff) |
Succeeds in passing simple read test
-rw-r--r-- | gcc/ipa-hello-world.c | 193 | ||||
-rw-r--r-- | gcc/ipa-str-reorg-dead-field-eliminate.c | 14 | ||||
-rw-r--r-- | gcc/ipa-str-reorg-utils.c | 15 | ||||
-rw-r--r-- | gcc/ipa-str-reorg-utils.h | 12 | ||||
-rw-r--r-- | gcc/ipa-type-escape-analysis.c | 12 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/ipa/ipa-access-counter-00-simple-read-0.c | 2 |
6 files changed, 220 insertions, 28 deletions
diff --git a/gcc/ipa-hello-world.c b/gcc/ipa-hello-world.c index cb69b1ea713..1ec86ff5bb6 100644 --- a/gcc/ipa-hello-world.c +++ b/gcc/ipa-hello-world.c @@ -22,11 +22,15 @@ #include "stringpool.h" #include "attribs.h" #include "tree-cfg.h" +#include "gimple.h" +#include "cfg.h" // needed for gimple-iterator.h +#include "gimple-iterator.h" #include <map> #include <set> #include "ipa-type-escape-analysis.h" +#include "ipa-str-reorg-utils.h" //TODO: place in header file @@ -41,6 +45,8 @@ print_function (cgraph_node *cnode) } typedef std::pair<const_tree /* record */, const_tree /* field */> fields; +//TODO: do not use pair. +//This names are unintelligible typedef std::pair<unsigned /* reads */, unsigned /* writes */> accesses; struct field_comparator { @@ -55,6 +61,9 @@ struct field_comparator 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; + log("left type is weird %s\n", get_type_name(left_record)); + gcc_assert(is_left_record_type); + gcc_assert(is_right_record_type); const bool are_left_and_right_valid = is_left_record_type && is_right_record_type; gcc_assert(are_left_and_right_valid); @@ -96,6 +105,183 @@ struct field_comparator typedef std::map<fields, accesses, field_comparator> field_access_counter; typedef std::set<const_tree> record_set; +enum access_code { READ_ACCESS, WRITE_ACCESS }; + +void +count_access_for_type_in_component_ref(const_tree component_ref, const record_set &non_escaping_records, field_access_counter &counter, const enum access_code access) +{ + gcc_assert(component_ref); + enum tree_code tree_code_component_ref = TREE_CODE(component_ref); + const bool is_component_ref = COMPONENT_REF == tree_code_component_ref; + gcc_assert(is_component_ref); + + const_tree _struct = TREE_OPERAND(component_ref, 0); + gcc_assert(_struct); + const_tree tree_type_struct = TREE_TYPE(_struct); + gcc_assert(tree_type_struct); + enum tree_code tree_type_struct_code = TREE_CODE(tree_type_struct); + const bool is_record_type = RECORD_TYPE == tree_type_struct_code; + gcc_assert(is_record_type); + + //FIXME: Future proofing or makinng things more difficult to read? + const bool in_set = +#if __cplusplus > 201703L + non_escaping_records.contains(tree_type_struct) +#else + non_escaping_records.find(tree_type_struct) != non_escaping_records.end() +#endif + ; + + log("%s is in non_escaping_records ? %s\n", get_type_name(tree_type_struct), in_set ? "true" : "false"); + if (!in_set) return; + + const_tree field = TREE_OPERAND(component_ref, 1); + gcc_assert(field); + enum tree_code tree_code_field = TREE_CODE(field); + const bool is_field_decl = FIELD_DECL == tree_code_field; + gcc_assert(is_field_decl); + + const std::pair<const_tree, const_tree> struct_field_pair = std::make_pair(tree_type_struct, field); + accesses &access_counter = counter[struct_field_pair]; + + switch (access) + { + case READ_ACCESS: + //TODO: do not use pair. + //This names are unintelligible + access_counter.first++; + log("%s.%s read %d\n", get_type_name(tree_type_struct), get_field_name(field), access_counter.first); + break; + case WRITE_ACCESS: + break; + //TODO: do not use pair. + //This names are unintelligible + access_counter.second++; + log("%s.%s write %d\n", get_type_name(tree_type_struct), get_field_name(field), access_counter.second); + default: + gcc_unreachable(); + break; + } +} + +void +count_access_for_types_in_expr(const_tree expr, const record_set &non_escaping_records, field_access_counter &counter, const enum access_code access) +{ + gcc_assert(expr); + enum tree_code tree_code_expr = TREE_CODE(expr); + switch (tree_code_expr) + { + case COMPONENT_REF: count_access_for_type_in_component_ref(expr, non_escaping_records, counter, access); break; + default: break; + } +} + +void +count_access_for_types_in_lhs(gimple *stmt, const record_set &non_escaping_records, field_access_counter &counter) +{ + gcc_assert(stmt); + const enum gimple_code gimple_code_stmt = gimple_code(stmt); + const bool is_assign = GIMPLE_ASSIGN == gimple_code_stmt; + gcc_assert(is_assign); + + const_tree lhs = gimple_assign_lhs (stmt); + //FIXME: I think if we do not access from GIMPLE_ASSIGN + //this is no longer an invariant... + gcc_assert(lhs); + count_access_for_types_in_expr(lhs, non_escaping_records, counter, WRITE_ACCESS); +} + +void +count_access_for_types_in_rhs(gimple *stmt, const record_set &non_escaping_records, field_access_counter &counter) +{ + gcc_assert(stmt); + const enum gimple_code gimple_code_stmt = gimple_code(stmt); + const bool is_assign = GIMPLE_ASSIGN == gimple_code_stmt; + gcc_assert(is_assign); + + const enum gimple_rhs_class gimple_rhs_class_stmt = gimple_assign_rhs_class(stmt); + switch (gimple_rhs_class_stmt) + { + case GIMPLE_TERNARY_RHS: + { + log("gimple_ternary_rhs\n"); + } + /* fall through */ + case GIMPLE_BINARY_RHS: + { + log("gimple_binary_rhs\n"); + } + /* fall through */ + case GIMPLE_SINGLE_RHS: + case GIMPLE_UNARY_RHS: + { + const_tree rhs1 = gimple_assign_rhs1(stmt); + gcc_assert(rhs1); + count_access_for_types_in_expr(rhs1, non_escaping_records, counter, READ_ACCESS); + log("gimple_single_rhs\n"); + } + break; + default: + gcc_unreachable(); + break; + } +} + +void +count_access_for_types_in_assign(gimple *stmt, const record_set &non_escaping_records, field_access_counter &counter) +{ + gcc_assert(stmt); + const enum gimple_code gimple_code_stmt = gimple_code(stmt); + const bool is_assign = GIMPLE_ASSIGN == gimple_code_stmt; + gcc_assert(is_assign); + + count_access_for_types_in_rhs(stmt, non_escaping_records, counter); + count_access_for_types_in_lhs(stmt, non_escaping_records, counter); +} + +void +count_access_for_types_in_stmt(gimple *stmt, const record_set &non_escaping_records, field_access_counter &counter) +{ + gcc_assert(stmt); + const enum gimple_code gimple_code_stmt = gimple_code(stmt); + switch(gimple_code_stmt) + { + case GIMPLE_ASSIGN: + count_access_for_types_in_assign(stmt, non_escaping_records, counter); + break; + default: + break; + } +} + +void +count_access_for_types_in_bb(basic_block bb, const record_set &non_escaping_records, field_access_counter &counter) +{ + gcc_assert(bb); + for (gimple_stmt_iterator gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) + { + gimple *stmt = gsi_stmt(gsi); + count_access_for_types_in_stmt(stmt, non_escaping_records, counter); + } +} + +void +count_access_for_types_in_function(cgraph_node *cnode, const record_set &non_escaping_records, field_access_counter &counter) +{ + gcc_assert(cnode); + tree decl = cnode->decl; + gcc_assert(decl); + function *func = DECL_STRUCT_FUNCTION (decl); + gcc_assert(func); + push_cfun(func); + basic_block bb = NULL; + FOR_EACH_BB_FN (bb, func) + { + gcc_assert(bb); + count_access_for_types_in_bb(bb, non_escaping_records, counter); + } + pop_cfun(); +} /* INFO: * Yes, I know we are returning a std::map. @@ -109,7 +295,7 @@ typedef std::set<const_tree> record_set; * for std::map and std::set */ field_access_counter -count_access_for_types(record_set &non_escaping_records) +count_access_for_types_in_linking_unit(const record_set &non_escaping_records) { field_access_counter counter; cgraph_node *cnode = NULL; @@ -117,6 +303,7 @@ count_access_for_types(record_set &non_escaping_records) { gcc_assert(cnode); print_function(cnode); + count_access_for_types_in_function(cnode, non_escaping_records, counter); } return counter; } @@ -155,8 +342,8 @@ 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); + const record_set non_escaping_records = calculate_non_escaping_records(escaping_types); + field_access_counter counter = count_access_for_types_in_linking_unit(non_escaping_records); return 0; } diff --git a/gcc/ipa-str-reorg-dead-field-eliminate.c b/gcc/ipa-str-reorg-dead-field-eliminate.c index ddb7b74b30a..f110b4e7585 100644 --- a/gcc/ipa-str-reorg-dead-field-eliminate.c +++ b/gcc/ipa-str-reorg-dead-field-eliminate.c @@ -519,20 +519,6 @@ get_field_offset (const_tree field) return offset; } -static const char * -get_field_name (const_tree field_decl) -{ - gcc_assert (field_decl); - gcc_assert (TREE_CODE (field_decl) == FIELD_DECL); - // TODO: deal with anonymous fields. - tree id = DECL_NAME (field_decl); - if (!id) - return "anonymous"; - gcc_assert (id); - const char *identifier = IDENTIFIER_POINTER (id); - gcc_assert (identifier); - return identifier; -} static const_tree get_field_with_offset_unsafe (const_tree record, const unsigned offset) diff --git a/gcc/ipa-str-reorg-utils.c b/gcc/ipa-str-reorg-utils.c index af2ec906911..cc6d5162af5 100644 --- a/gcc/ipa-str-reorg-utils.c +++ b/gcc/ipa-str-reorg-utils.c @@ -283,3 +283,18 @@ get_type_name (const_tree type) } return NULL; } + +const char * +get_field_name (const_tree field_decl) +{ + gcc_assert (field_decl); + gcc_assert (TREE_CODE (field_decl) == FIELD_DECL); + // TODO: deal with anonymous fields. + tree id = DECL_NAME (field_decl); + if (!id) + return "anonymous"; + gcc_assert (id); + const char *identifier = IDENTIFIER_POINTER (id); + gcc_assert (identifier); + return identifier; +} diff --git a/gcc/ipa-str-reorg-utils.h b/gcc/ipa-str-reorg-utils.h index 4874929afb7..1465db03d31 100644 --- a/gcc/ipa-str-reorg-utils.h +++ b/gcc/ipa-str-reorg-utils.h @@ -29,7 +29,19 @@ const_tree get_base_type_from_array_type (const_tree array_type); const_tree get_base_type_from_pointer_type (const_tree pointer_type, unsigned int &indirection_level); const_tree get_base_type_from_pointer_type (const_tree pointer_type); const_tree get_base_type (const_tree type); +const char* get_field_name (const_tree type); +#include <stdio.h> +inline void +log (const char * const format, ...) +{ + if (!dump_file) return; + + va_list args; + va_start(args, format); + vfprintf(dump_file, format, args); + va_end(args); +} #endif diff --git a/gcc/ipa-type-escape-analysis.c b/gcc/ipa-type-escape-analysis.c index b005fe362ec..a8163cd501f 100644 --- a/gcc/ipa-type-escape-analysis.c +++ b/gcc/ipa-type-escape-analysis.c @@ -32,18 +32,8 @@ #include "ipa-str-reorg-utils.h" #include "ipa-type-escape-analysis.h" -// First we need to collect all types -void -log (const char * const format, ...) -{ - if (!dump_file) return; - - va_list args; - va_start(args, format); - vfprintf(dump_file, format, args); - va_end(args); -} +// First we need to collect all types static bool filter_type (type_map &escape_map, const_tree type); diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-access-counter-00-simple-read-0.c b/gcc/testsuite/gcc.dg/ipa/ipa-access-counter-00-simple-read-0.c index c9e68989142..88f96ea3be4 100644 --- a/gcc/testsuite/gcc.dg/ipa/ipa-access-counter-00-simple-read-0.c +++ b/gcc/testsuite/gcc.dg/ipa/ipa-access-counter-00-simple-read-0.c @@ -11,7 +11,9 @@ int main () { printf("%d\n", astruct.a); + printf("%d\n", astruct.a); } /* { dg-final { scan-wpa-ipa-dump "collected,astruct_s" "hello-world" } } */ /* { dg-final { scan-wpa-ipa-dump "astruct_s.a read 1" "hello-world" } } */ +/* { dg-final { scan-wpa-ipa-dump "astruct_s.a read 2" "hello-world" } } */ |