summaryrefslogtreecommitdiff
path: root/gcc/ipa-hello-world.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ipa-hello-world.c')
-rw-r--r--gcc/ipa-hello-world.c151
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),