diff options
author | Erick Ochoa <erick.ochoa@theobroma-systems.com> | 2020-06-15 15:45:33 +0200 |
---|---|---|
committer | Erick Ochoa <erick.ochoa@theobroma-systems.com> | 2020-06-16 08:58:13 +0200 |
commit | 57dde08f7d34c88edb7cce7046f2424de605c4a1 (patch) | |
tree | e308b54628c4feb4ede4ae40d2bd4b16b2c532da | |
parent | 4a28abd0fc3e5a413d4459e3c69f7cffdf87e8a9 (diff) |
better type renaming
-rw-r--r-- | gcc/testsuite/gcc.dg/ipa/ipa-structreorg-06-pointer-struct-0.c | 22 | ||||
-rw-r--r-- | gcc/type-reconstructor.c | 72 | ||||
-rw-r--r-- | gcc/type-reconstructor.hpp | 3 |
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; }; }; |