summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErick Ochoa <erick.ochoa@theobroma-systems.com>2020-06-15 15:45:33 +0200
committerErick Ochoa <erick.ochoa@theobroma-systems.com>2020-06-16 08:58:13 +0200
commit57dde08f7d34c88edb7cce7046f2424de605c4a1 (patch)
treee308b54628c4feb4ede4ae40d2bd4b16b2c532da
parent4a28abd0fc3e5a413d4459e3c69f7cffdf87e8a9 (diff)
better type renaming
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipa-structreorg-06-pointer-struct-0.c22
-rw-r--r--gcc/type-reconstructor.c72
-rw-r--r--gcc/type-reconstructor.hpp3
3 files changed, 93 insertions, 4 deletions
diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-06-pointer-struct-0.c b/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-06-pointer-struct-0.c
new file mode 100644
index 00000000000..dceab124b4b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-06-pointer-struct-0.c
@@ -0,0 +1,22 @@
+/* { dg-do link } */
+/* { dg-options "-flto -fipa-type-escape-analysis -fdump-ipa-type-escape-analysis -fprint-access-analysis " } */
+
+#include <stdio.h>
+
+struct astruct_s { float a; _Bool b; int c;};
+struct ostruct_s { struct astruct_s *a; float b; float c; };
+struct ostruct_s ostruct;
+
+
+int
+main ()
+{
+ printf("%d\n", ostruct.b);
+ printf("%d\n", ostruct.c);
+ printf("%f\n", ostruct.a->a);
+ printf("%d\n", ostruct.a->c);
+}
+
+/* { dg-final { scan-ipa-dump " record astruct_s ... -> record astruct_s ..." "type-escape-analysis" } } */
+/* { dg-final { scan-ipa-dump " record ostruct_s . record astruct_s ... a;real_type b;real_type c;. -> record ostruct_s . record astruct_s ... a;real_type b;real_type c;." "type-escape-analysis" } } */
+/* { dg-final { scan-ipa-dump " record astruct_s .real_type a;boolean_type b;integer_type c.. -> record astruct_s .real_type a;integer_type c.." "type-escape-analysis" } } */
diff --git a/gcc/type-reconstructor.c b/gcc/type-reconstructor.c
index c4f225f358d..39ef4aea385 100644
--- a/gcc/type-reconstructor.c
+++ b/gcc/type-reconstructor.c
@@ -34,6 +34,56 @@
#include "type-stringifier.hpp"
#include "stor-layout.h"
+bool
+TypeReconstructor::is_memoized(const_tree t)
+{
+ const bool already_changed = _reorg_map.find(t) != _reorg_map.end();
+ return already_changed;
+}
+
+static tree
+get_new_identifier(const_tree type)
+{
+ const char* identifier = TypeStringifier::get_type_identifier(type).c_str();
+ const bool is_new_type = strstr(identifier, "reorg");
+ gcc_assert(!is_new_type);
+ char *new_name;
+ asprintf(&new_name, "%s.reorg", identifier);
+ log("old %s new %s\n", identifier, new_name);
+ return get_identifier(new_name);
+}
+
+void
+TypeReconstructor::_walk_POINTER_TYPE_pre(const_tree t)
+{
+ // We really should only make a distinct type copy if
+ // it points to a pointer that will be rewritten...
+ _working_stack.push(build_distinct_type_copy((tree)t));
+}
+
+void
+TypeReconstructor::_walk_POINTER_TYPE_post(const_tree t)
+{
+ const bool already_changed = _reorg_map.find(t) != _reorg_map.end();
+ const_tree modifications = _working_stack.top();
+ _working_stack.pop();
+ if (already_changed) return;
+
+ tree tt = TREE_TYPE(t);
+ bool field_type_in_reorg_map = _reorg_map.find(tt) != _reorg_map.end();
+ if (!field_type_in_reorg_map) {
+ TYPE_NAME((tree)modifications) = get_new_identifier(modifications);
+ _reorg_map[t] = modifications;
+ return;
+ }
+
+ log ("here\n");
+ tree tf = (tree)_reorg_map[tt];
+ TREE_TYPE((tree)modifications) = tf;
+ TYPE_NAME((tree)modifications) = get_new_identifier(modifications);
+ _reorg_map[t] = modifications;
+}
+
void
TypeReconstructor::_walk_RECORD_TYPE_pre(const_tree t)
{
@@ -45,8 +95,8 @@ TypeReconstructor::_walk_RECORD_TYPE_pre(const_tree t)
field_offsets_t empty;
_record_stack.push(in_map ? _records[t] : empty);
- // Do we create a record here?
- // Which is a copy of the old one?
+ // We really should only make a distinct type copy if
+ // it points to a pointer that will be rewritten...
_working_stack.push(build_distinct_type_copy((tree)t));
type_vector_t vec;
@@ -55,14 +105,15 @@ TypeReconstructor::_walk_RECORD_TYPE_pre(const_tree t)
_eliminated_fields.push(vec2);
}
+
void
TypeReconstructor::_walk_RECORD_TYPE_post(const_tree t)
{
+ const bool already_changed = _reorg_map.find(t) != _reorg_map.end();
type_vector_t fields_to_keep = _field_decls.top();
for (auto i = fields_to_keep.cbegin(), e = fields_to_keep.cend(); i != e; ++i)
{
const_tree field = *i;
- log("I will keep %s\n", TypeStringifier::get_field_identifier(field).c_str());
}
type_vector_t fields_to_eliminate = _eliminated_fields.top();
_eliminated_fields.pop();
@@ -80,7 +131,17 @@ TypeReconstructor::_walk_RECORD_TYPE_post(const_tree t)
// There are no fields to keep
// Can be an incomplete type
- if (fields_to_keep.empty()) return;
+
+ // It is already changed, so just pop the stacks and that's it.
+ if (already_changed) return;
+
+ if (fields_to_keep.empty())
+ {
+ layout_type((tree)working_type);
+ TYPE_NAME((tree)working_type) = get_new_identifier(working_type);
+ _reorg_map[t] = working_type;
+ return;
+ }
tree f = (tree) fields_to_keep[0];
tree tf = TREE_TYPE(f);
@@ -106,9 +167,12 @@ TypeReconstructor::_walk_RECORD_TYPE_post(const_tree t)
}
layout_type((tree)working_type);
+ TYPE_NAME((tree)working_type) = get_new_identifier(working_type);
_reorg_map[t] = working_type;
}
+
+
void
TypeReconstructor::_walk_field_pre(const_tree t)
{
diff --git a/gcc/type-reconstructor.hpp b/gcc/type-reconstructor.hpp
index c802f59ebec..ca596c5d86d 100644
--- a/gcc/type-reconstructor.hpp
+++ b/gcc/type-reconstructor.hpp
@@ -33,7 +33,10 @@ private:
virtual void _walk_field_post(const_tree);
virtual void _walk_RECORD_TYPE_pre(const_tree);
virtual void _walk_RECORD_TYPE_post(const_tree);
+ virtual void _walk_POINTER_TYPE_pre(const_tree);
+ virtual void _walk_POINTER_TYPE_post(const_tree);
public:
+ virtual bool is_memoized(const_tree t);
TypeReconstructor(record_field_offset_map_t records) : _records(records) {};
reorg_record_map_t get_map() { return _reorg_map; };
};