summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErick Ochoa <erick.ochoa@theobroma-systems.com>2020-03-10 16:30:54 +0100
committerErick Ochoa <erick.ochoa@theobroma-systems.com>2020-06-03 16:05:21 +0200
commit136f2749fd3ac846a8e5be2cbbf32abdb7b9e179 (patch)
tree2d4b4d1863d8c85fa70df22305379c96581ddbb1
parente4389908cc090e769b94051c7ddef4136565173c (diff)
Succeeds in passing simple read test
-rw-r--r--gcc/ipa-hello-world.c193
-rw-r--r--gcc/ipa-str-reorg-dead-field-eliminate.c14
-rw-r--r--gcc/ipa-str-reorg-utils.c15
-rw-r--r--gcc/ipa-str-reorg-utils.h12
-rw-r--r--gcc/ipa-type-escape-analysis.c12
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipa-access-counter-00-simple-read-0.c2
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" } } */