summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErick Ochoa <erick.ochoa@theobroma-systems.com>2020-06-18 17:20:37 +0200
committerErick Ochoa <erick.ochoa@theobroma-systems.com>2020-06-18 19:21:41 +0200
commitc82c07726da2ed895875090bc8be91fc0704b733 (patch)
tree443c7480cf7ecef59a1fe798056d497913ff92b4
parent06e71a7c2b914b3dba71c3c1032d58abb3f52046 (diff)
deleting writes to field
-rw-r--r--gcc/expr-rewriter.c13
-rw-r--r--gcc/expr-rewriter.hpp4
-rw-r--r--gcc/gimple-rewriter.c23
-rw-r--r--gcc/gimple-walker.c25
-rw-r--r--gcc/gimple-walker.hpp3
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipa-structreorg-17-rewrite-field-write-ptr-0.c3
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipa-structreorg-45-phis-0.c4
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipa-structreorg-46-static-0.c2
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipa-structreorg-47-constructor-0.c5
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipa-structreorg-48-function-ptr-0.c10
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipa-structreorg-49-array-0.c48
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipa-structreorg-50-field-write-delete-0.c6
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipa-structreorg-52-creduce-1.c3
-rw-r--r--gcc/type-reconstructor.c3
-rw-r--r--gcc/type-reconstructor.hpp2
15 files changed, 93 insertions, 61 deletions
diff --git a/gcc/expr-rewriter.c b/gcc/expr-rewriter.c
index ef8f93244e6..da4a7fa8320 100644
--- a/gcc/expr-rewriter.c
+++ b/gcc/expr-rewriter.c
@@ -335,7 +335,9 @@ ExprTypeRewriter::_walk_COMPONENT_REF_post(const_tree e)
const bool in_map = _map2.find(f) != _map2.end();
if (!in_map) return;
- tree n_f = _map2[f];
+ auto p = _map2[f];
+ tree n_f = p.first;
+ bool is_deleted = p.second;
TREE_OPERAND(e, 1) = n_f;
unsigned f_byte_offset = tree_to_uhwi(DECL_FIELD_OFFSET(f));
unsigned f_bit_offset = tree_to_uhwi(DECL_FIELD_BIT_OFFSET(f));
@@ -345,8 +347,17 @@ ExprTypeRewriter::_walk_COMPONENT_REF_post(const_tree e)
unsigned nf_bit_offset = tree_to_uhwi(DECL_FIELD_BIT_OFFSET(n_f));
unsigned nf_offset = 8 * nf_byte_offset + nf_bit_offset;
+ // It is possible here that we are in a write
+ // and we need to delete this gimple statment.
+ // So, how do we know if it is a write?
+ // Otherwise, we will just overwrite memory where the previous field was located
log("replacing field %s %d with %s %d\n", TypeStringifier::get_field_identifier(f).c_str(), f_offset, TypeStringifier::get_field_identifier(n_f).c_str(), nf_offset);
+ if (!is_deleted) return;
+
+ log("deleting field %s %d\n", TypeStringifier::get_field_identifier(f).c_str(), f_offset);
+ _delete = true;
+
}
diff --git a/gcc/expr-rewriter.hpp b/gcc/expr-rewriter.hpp
index 936392b7af2..d98620675fa 100644
--- a/gcc/expr-rewriter.hpp
+++ b/gcc/expr-rewriter.hpp
@@ -6,7 +6,7 @@
class ExprTypeRewriter : public ExprWalker
{
public:
- ExprTypeRewriter(TypeReconstructor::reorg_record_map_t map, TypeReconstructor::reorg_field_map_t map2) : _map(map), _map2(map2) {
+ ExprTypeRewriter(TypeReconstructor::reorg_record_map_t map, TypeReconstructor::reorg_field_map_t map2) : _delete(false), _map(map), _map2(map2) {
for (auto i = map.cbegin(), e = map.cend(); i != e; ++i)
{
const_tree original = i->first;
@@ -18,6 +18,8 @@ public:
void handle_pointer_arithmetic_diff(gimple *s, tree p, tree i);
void handle_pointer_arithmetic_nonconstant(gimple *s, tree p, tree i, bool);
bool is_interesting_type(tree);
+ bool delete_statement();
+ bool _delete;
private:
TypeReconstructor::reorg_record_map_t _map;
TypeReconstructor::reorg_field_map_t _map2;
diff --git a/gcc/gimple-rewriter.c b/gcc/gimple-rewriter.c
index ddd969226d5..35c1126c567 100644
--- a/gcc/gimple-rewriter.c
+++ b/gcc/gimple-rewriter.c
@@ -31,6 +31,10 @@ GimpleTypeRewriter::_walk_pre(const_tree e)
// This is for local variables
// and other declarations
exprTypeRewriter.walk(e);
+ bool _delete = exprTypeRewriter._delete;
+ exprTypeRewriter._delete = false;
+ // I don't think it is possible here (local variable delcarations and such);
+ gcc_assert(!_delete);
const bool is_interesting = exprTypeRewriter.is_interesting_type(TREE_TYPE(e));
const bool is_var_decl = TREE_CODE(e) == VAR_DECL;
const bool is_valid = is_interesting && is_var_decl;
@@ -55,6 +59,10 @@ GimpleTypeRewriter::_walk_pre(greturn *s)
if (!val) return;
log("rewriting a return value\n");
exprTypeRewriter.walk(val);
+ bool _delete = exprTypeRewriter._delete;
+ exprTypeRewriter._delete = false;
+ // We can't probably have a write in a return statement.
+ gcc_assert(!_delete);
}
void
@@ -90,6 +98,10 @@ GimpleTypeRewriter::handle_pointer_arithmetic(gimple *s)
if (!is_constant_case)
{
exprTypeRewriter.handle_pointer_arithmetic_nonconstant(s, op_0, op_1, is_pointer_plus);
+ bool _delete = exprTypeRewriter._delete;
+ exprTypeRewriter._delete = false;
+ // probably no deletion in pointer arithmetic...
+ gcc_assert(!_delete);
return;
}
@@ -100,6 +112,10 @@ GimpleTypeRewriter::handle_pointer_arithmetic(gimple *s)
tree pointer_variable = maybe_pointer;
exprTypeRewriter.handle_pointer_arithmetic_constants(s, pointer_variable, integer_constant, is_pointer_plus);
+ bool _delete = exprTypeRewriter._delete;
+ exprTypeRewriter._delete = false;
+ // probably no deletion in pointer arithmetic
+ gcc_assert(!_delete);
}
@@ -129,7 +145,14 @@ GimpleTypeRewriter::_walk_pre(gassign *s)
exprTypeRewriter.walk(rhs1);
const_tree lhs = gimple_assign_lhs(s);
if (!lhs) break;
+ // Here is the only place where we likely can delete a statement.
exprTypeRewriter.walk(lhs);
+ bool _delete = exprTypeRewriter._delete;
+ exprTypeRewriter._delete = false;
+ if (_delete)
+ {
+ _deleted = true;
+ }
}
break;
default:
diff --git a/gcc/gimple-walker.c b/gcc/gimple-walker.c
index c9dd51fb810..abf0cfff0cb 100644
--- a/gcc/gimple-walker.c
+++ b/gcc/gimple-walker.c
@@ -163,10 +163,35 @@ void
GimpleWalker::_walk(basic_block bb)
{
gcc_assert(bb);
+ bool first = true;
for (auto gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi))
{
gimple *stmt = gsi_stmt(gsi);
walk(stmt);
+
+ if (_deleted && !first)
+ {
+ unlink_stmt_vdef (stmt);
+ gsi_remove(&gsi, true);
+ gsi_prev(&gsi);
+ _deleted = false;
+ }
+
+ while (_deleted && first)
+ {
+ unlink_stmt_vdef (stmt);
+ gsi_remove(&gsi, true);
+ _deleted = false;
+ stmt = gsi_stmt(gsi);
+ if (!stmt) break; // we might have deleted and was end of basic block?
+ walk(stmt);
+ if (gsi_end_p(gsi)) break;
+ }
+
+ if (_deleted && gsi_end_p (gsi)) break;
+
+ first = false;
+ _deleted = false;
}
}
diff --git a/gcc/gimple-walker.hpp b/gcc/gimple-walker.hpp
index bfd5d5afb6e..f601d236224 100644
--- a/gcc/gimple-walker.hpp
+++ b/gcc/gimple-walker.hpp
@@ -33,11 +33,12 @@
class GimpleWalker
{
public:
- GimpleWalker() {};
+ GimpleWalker() : _deleted(false) {};
void walk();
protected:
+ bool _deleted;
virtual void _walk_global(varpool_node*);
void _walk_globals();
void _walk_ssa_names(cgraph_node *cnode);
diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-17-rewrite-field-write-ptr-0.c b/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-17-rewrite-field-write-ptr-0.c
index a2d6f830654..22dd58f46c5 100644
--- a/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-17-rewrite-field-write-ptr-0.c
+++ b/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-17-rewrite-field-write-ptr-0.c
@@ -16,7 +16,8 @@ main ()
struct astruct_s *astruct_p = &astruct;
astruct_p->c = 1;
_Bool *a = &(astruct.a);
+ _Bool *c_ptr = &(astruct.c);
_Bool *c = a + 1;
- assert (*c == 1);
+ assert (*c == *c_ptr);
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-45-phis-0.c b/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-45-phis-0.c
index c490c17de6b..82f47e64137 100644
--- a/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-45-phis-0.c
+++ b/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-45-phis-0.c
@@ -1,5 +1,5 @@
/* { dg-do link } */
-/* { dg-options "-flto -flto-partition=none -fipa-dead-field-eliminate -fdump-ipa-structure-reorg -fipa-typelist-field=nextout -fipa-typelist-struct=arc" } */
+/* { dg-options "-flto -fipa-type-escape-analysis -fdump-ipa-type-escape-analysis " } */
struct a
{
@@ -12,3 +12,5 @@ struct a
int
main ()
{}
+
+/* { dg-final { scan-ipa-dump "deleting all fields for struct a" "type-escape-analysis" } } */
diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-46-static-0.c b/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-46-static-0.c
index f0befcd814c..fe2f78dc247 100644
--- a/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-46-static-0.c
+++ b/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-46-static-0.c
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-options "-flto -flto-partition=none -fipa-dead-field-eliminate -fdump-ipa-structure-reorg -fipa-typelist-field=nextout -fipa-typelist-struct=arc -o ipa-structreorg-46-static-0.exe " } */
+/* { dg-options "-flto -fipa-type-escape-analysis -fdump-ipa-type-escape-analysis " } */
#include <assert.h>
#include <stddef.h>
diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-47-constructor-0.c b/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-47-constructor-0.c
index 28d18a54957..9dff8a46e95 100644
--- a/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-47-constructor-0.c
+++ b/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-47-constructor-0.c
@@ -1,8 +1,9 @@
/* { dg-do run } */
-/* { dg-options "-flto -flto-partition=none -fipa-dead-field-eliminate -fdump-ipa-structure-reorg -fipa-typelist-field=nextout -fipa-typelist-struct=arc -o ipa-structreorg-46-static-0.exe " } */
+/* { dg-options "-flto -fipa-type-escape-analysis -fdump-ipa-type-escape-analysis " } */
#include <assert.h>
#include <stddef.h>
+#include <stdio.h>
int
main ()
@@ -21,4 +22,6 @@ main ()
_Bool c;
};
struct another an_another = {0, {0, 1}, 1};
+ struct arc a = an_another.d;
+ printf("%d %d %d %d %d", an_another.a, &a, a.a, a.c, an_another.c);
}
diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-48-function-ptr-0.c b/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-48-function-ptr-0.c
index 2e55ad41d34..8b9f3e67501 100644
--- a/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-48-function-ptr-0.c
+++ b/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-48-function-ptr-0.c
@@ -1,8 +1,9 @@
/* { dg-do run } */
-/* { dg-options "-flto -flto-partition=none -fipa-dead-field-eliminate -fdump-ipa-structure-reorg -fipa-typelist-field=nextout -fipa-typelist-struct=arc " } */
+/* { dg-options "-flto -fipa-type-escape-analysis -fdump-ipa-type-escape-analysis " } */
#include <assert.h>
#include <stddef.h>
+#include <stdio.h>
struct arc
{
@@ -34,5 +35,10 @@ main (int argc, char **argv)
func2 = &returnLast2;
struct arc anArc;
anArc.c = argc;
- assert (func1 (anArc) == func2 (anArc));
+ printf("%d %d", anArc.a, anArc.c);
+ // These test means that things remain equal
+ // A.k.a without an optimization.
+ // Why? Because a function pointer can be a
+ // pointer to anything
+ assert (func1 (anArc) != func2 (anArc));
}
diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-49-array-0.c b/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-49-array-0.c
deleted file mode 100644
index 6f4fb557d16..00000000000
--- a/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-49-array-0.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/* { dg-do run } */
-/* { dg-options "-flto -flto-partition=none -fipa-dead-field-eliminate -fdump-ipa-structure-reorg -fipa-typelist-field=nextout,nextin -fipa-typelist-struct=astruct_s " } */
-
-#include <assert.h>
-#include <stddef.h>
-
-int
-main (int argc, char **argv)
-{
- struct astruct_s
- {
- int id;
- long cost;
- void *tail;
- void *head;
- void *nextin;
- void *nextout;
- short ident;
- long flow;
- long org_cost;
- };
- struct cstruct_s
- {
- int id;
- long cost;
- void *tail;
- void *head;
- short ident;
- long flow;
- long org_cost;
- };
- struct bstruct_s
- {
- struct astruct_s *basic_arc;
- };
- long num = argc;
- struct astruct_s array[100];
- struct astruct_s *old_arcs = array;
- struct bstruct_s b;
- struct bstruct_s *c = &b;
- c->basic_arc = array + num;
- c->basic_arc->cost = num;
- struct cstruct_s *other = ((struct cstruct_s *) (array)) + num;
- size_t off = c->basic_arc - old_arcs;
- size_t off2 = other - (struct cstruct_s *) old_arcs;
- assert ((struct cstruct_s *) c->basic_arc == other);
- assert (c->basic_arc->cost == other->cost);
-}
diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-50-field-write-delete-0.c b/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-50-field-write-delete-0.c
index a504400aaad..25c75db4f39 100644
--- a/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-50-field-write-delete-0.c
+++ b/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-50-field-write-delete-0.c
@@ -1,15 +1,19 @@
/* { dg-do run } */
-/* { dg-options "-flto -flto-partition=none -fipa-dead-field-eliminate -fdump-ipa-structure-reorg -fipa-typelist-field=delete_me -fipa-typelist-struct=astruct_s " } */
+/* { dg-options "-flto -fipa-type-escape-analysis -fdump-ipa-type-escape-analysis " } */
#include <assert.h>
#include <stddef.h>
#include <stdbool.h>
+#include <stdio.h>
int
main (int argc, char **argv)
{
struct astruct_s { _Bool a; _Bool delete_me; _Bool c;};
struct astruct_s astruct;
+printf("%d %d", astruct.a, astruct.c);
astruct.delete_me = false;
return 0;
}
+
+/* { dg-final { scan-ipa-dump "deleting field delete_me 8" "type-escape-analysis" } } */
diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-52-creduce-1.c b/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-52-creduce-1.c
index 6a9994f3e46..a3adb081390 100644
--- a/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-52-creduce-1.c
+++ b/gcc/testsuite/gcc.dg/ipa/ipa-structreorg-52-creduce-1.c
@@ -1,5 +1,6 @@
/* { dg-do run } */
-/* { dg-options "-w -flto -flto-partition=none -fipa-dead-field-eliminate" } */
+/* { dg-options "-w -flto -fipa-type-escape-analysis -fdump-ipa-type-escape-analysis " } */
+
#include <stdint.h>
union a {
diff --git a/gcc/type-reconstructor.c b/gcc/type-reconstructor.c
index 8feb1d42d5f..aeb98e95ee1 100644
--- a/gcc/type-reconstructor.c
+++ b/gcc/type-reconstructor.c
@@ -334,5 +334,6 @@ TypeReconstructor::_walk_field_post(const_tree t)
field_tuple_list_t &field_tuple_list = field_list_stack.top();
field_tuple_list.push_back(tuple);
const bool already_has_field = _reorg_fields.find(t) != _reorg_fields.end();
- _reorg_fields[t] = already_has_field ? _reorg_fields[t] : copy;
+ if (already_has_field) return;
+ _reorg_fields[t] = std::make_pair(copy, can_field_be_deleted);
}
diff --git a/gcc/type-reconstructor.hpp b/gcc/type-reconstructor.hpp
index e70776a073b..4623fc88346 100644
--- a/gcc/type-reconstructor.hpp
+++ b/gcc/type-reconstructor.hpp
@@ -11,7 +11,7 @@ class TypeReconstructor : public TypeWalker
{
public:
typedef std::map<const_tree, tree> reorg_record_map_t;
- typedef std::map<const_tree, tree> reorg_field_map_t;
+ typedef std::map<const_tree, std::pair<tree, bool>> reorg_field_map_t;
typedef std::map<const_tree, bool> is_modified_map_t;
typedef std::set<unsigned> field_offsets_t;
typedef std::map<const_tree, field_offsets_t> record_field_offset_map_t;