summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErick Ochoa <erick.ochoa@theobroma-systems.com>2020-06-10 08:31:15 +0200
committerErick Ochoa <erick.ochoa@theobroma-systems.com>2020-06-10 11:48:31 +0200
commit6772b81536fe5f5a1852cf090d6847c961a4d73e (patch)
tree86df5488848a611868c11494ea7e1da3f0b3a2ab
parentea839b8d57733aecc413b4b91935fb59d04a3303 (diff)
Adds GimpleAccessor and ExprAccessor
These classes will determine whether either READ or WRITE accesses occur to fields in structures. Tests for determining accesses are passing
-rw-r--r--gcc/Makefile.in2
-rw-r--r--gcc/common.opt4
-rw-r--r--gcc/expr-accessor.c82
-rw-r--r--gcc/expr-accessor.hpp27
-rw-r--r--gcc/gimple-accesser.c105
-rw-r--r--gcc/gimple-accesser.hpp24
-rw-r--r--gcc/gimple-caster.c61
-rw-r--r--gcc/gimple-caster.hpp5
-rw-r--r--gcc/gimple-escaper.c3
-rw-r--r--gcc/gimple-escaper.hpp2
-rw-r--r--gcc/gimple-walker.c2
-rw-r--r--gcc/ipa-prototype.h2
-rw-r--r--gcc/ipa-type-escape-analysis.c7
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipa-access-counter-00-simple-read-0.c7
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipa-access-counter-01-simple-write-0.c7
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipa-access-counter-02-pointer-read-0.c7
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipa-access-counter-03-pointer-write-0.c7
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipa-access-counter-04-gimple-cond-0.c6
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipa-ea-16-parameter-cast-0.c20
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipa-ea-17-malloc-0.c17
-rw-r--r--gcc/type-incomplete-equality.c6
-rw-r--r--gcc/type-walker.c2
22 files changed, 372 insertions, 33 deletions
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 1f7a349a4c6..bf0623be999 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1412,6 +1412,8 @@ OBJS = \
type-walker.o \
expr-walker.o \
gimple-walker.o \
+ gimple-accesser.o \
+ expr-accessor.o \
type-collector.o \
expr-collector.o \
gimple-collector.o \
diff --git a/gcc/common.opt b/gcc/common.opt
index ec351e2f96f..ddc872e8c5b 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -3466,4 +3466,8 @@ fprint-cast-analysis
Common Report Var(flag_print_cast_analysis) Optimization
This flag is used to print the escape analysis including type casting.
+fprint-access-analysis
+Common Report Var(flag_print_access_analysis) Optimization
+This flag is used to print the access analysis (if field is read or written to).
+
; This comment is to ensure we retain the blank line above.
diff --git a/gcc/expr-accessor.c b/gcc/expr-accessor.c
new file mode 100644
index 00000000000..594c8d553d6
--- /dev/null
+++ b/gcc/expr-accessor.c
@@ -0,0 +1,82 @@
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "tree.h"
+#include "gimple-expr.h"
+#include "predict.h"
+#include "alloc-pool.h"
+#include "tree-pass.h"
+#include "cgraph.h"
+#include "diagnostic.h"
+#include "fold-const.h"
+#include "gimple-fold.h"
+#include "symbol-summary.h"
+#include "tree-vrp.h"
+#include "ipa-prop.h"
+#include "tree-pretty-print.h"
+#include "tree-inline.h"
+#include "ipa-fnsummary.h"
+#include "ipa-utils.h"
+#include "tree-ssa-ccp.h"
+#include "stringpool.h"
+#include "attribs.h"
+#include "tree-ssa-alias.h"
+#include "tree-ssanames.h"
+#include "gimple.h"
+#include "cfg.h" // needed for gimple-iterator.h
+#include "gimple-iterator.h"
+#include "gimple-ssa.h"
+#include <stdbool.h>
+
+
+#include "types-inlines.h"
+#include "type-stringifier.hpp"
+#include "expr-accessor.hpp"
+#include "expr-walker.hpp"
+
+void
+ExprAccessor::update(const_tree e, unsigned access)
+{
+ _access = access;
+ walk(e);
+}
+
+void
+ExprAccessor::_walk_COMPONENT_REF_pre(const_tree e)
+{
+ assert_is_type(e, COMPONENT_REF);
+ const_tree op0 = TREE_OPERAND(e, 0);
+ gcc_assert(op0);
+ const_tree op0_t = TREE_TYPE(op0);
+ gcc_assert(op0_t);
+ const_tree op1 = TREE_OPERAND(e, 1);
+ assert_is_type(op1, FIELD_DECL);
+ const bool record_already_in_map = record_field_map.find(op0_t) != record_field_map.end();
+ field_access_map_t field_map;
+ field_map = record_already_in_map ? record_field_map[op0_t] : field_map;
+ const bool field_already_in_map = field_map.find(op1) != field_map.end();
+ unsigned prev_access = field_already_in_map ? field_map[op1] : Empty;
+
+ prev_access |= _access;
+ field_map[op1] = prev_access;
+ record_field_map[op0_t] = field_map;
+}
+
+void
+ExprAccessor::print_accesses()
+{
+ for (auto i = record_field_map.cbegin(), e = record_field_map.cend(); i != e; ++i)
+ {
+ const_tree record = i->first;
+ field_access_map_t field_map = i->second;
+ for (auto j = field_map.cbegin(), f = field_map.cend(); j != f; ++j)
+ {
+ const_tree field = j->first;
+ const std::string name_r = TypeStringifier::get_type_identifier(record);
+ const std::string name_f = TypeStringifier::get_field_identifier(field);
+ unsigned access = j->second;
+ log("%s.%s = 0x%04x\n", name_r.c_str(), name_f.c_str(), access);
+ }
+ }
+}
diff --git a/gcc/expr-accessor.hpp b/gcc/expr-accessor.hpp
new file mode 100644
index 00000000000..c3a0b4ecef7
--- /dev/null
+++ b/gcc/expr-accessor.hpp
@@ -0,0 +1,27 @@
+#pragma once
+
+#include "ipa-prototype.h"
+#include "expr-walker.hpp"
+#include "type-escaper.hpp"
+#include "collect-types.h"
+#include <tuple>
+#include <map>
+
+constexpr unsigned Empty = 0x0u;
+constexpr unsigned Read = 0x01u;
+constexpr unsigned Write = 0x02u;
+
+typedef std::map<const_tree, unsigned> field_access_map_t;
+typedef std::map<const_tree, field_access_map_t> record_field_map_t;
+
+class ExprAccessor : public ExprWalker
+{
+public:
+ ExprAccessor() {};
+ void update(const_tree e, unsigned a);
+ void print_accesses();
+private:
+ unsigned _access;
+ record_field_map_t record_field_map;
+ virtual void _walk_COMPONENT_REF_pre(const_tree e);
+};
diff --git a/gcc/gimple-accesser.c b/gcc/gimple-accesser.c
new file mode 100644
index 00000000000..18d74f499c0
--- /dev/null
+++ b/gcc/gimple-accesser.c
@@ -0,0 +1,105 @@
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "backend.h"
+#include "tree.h"
+#include "gimple-expr.h"
+#include "predict.h"
+#include "alloc-pool.h"
+#include "tree-pass.h"
+#include "cgraph.h"
+#include "diagnostic.h"
+#include "fold-const.h"
+#include "gimple-fold.h"
+#include "symbol-summary.h"
+#include "tree-vrp.h"
+#include "ipa-prop.h"
+#include "tree-pretty-print.h"
+#include "tree-inline.h"
+#include "ipa-fnsummary.h"
+#include "ipa-utils.h"
+#include "tree-ssa-ccp.h"
+#include "stringpool.h"
+#include "attribs.h"
+#include "tree-ssa-alias.h"
+#include "tree-ssanames.h"
+#include "gimple.h"
+#include "cfg.h"
+#include "gimple-iterator.h"
+#include "gimple-ssa.h"
+
+#include "types-inlines.h"
+#include "gimple-accesser.hpp"
+
+
+void
+GimpleAccesser::_walk_pre(gassign *s)
+{
+ // There seems to be quite a bit of code duplication here...
+ const enum gimple_rhs_class code = gimple_assign_rhs_class(s);
+ switch (code)
+ {
+ case GIMPLE_TERNARY_RHS:
+ {
+ const_tree rhs3 = gimple_assign_rhs3(s);
+ gcc_assert(rhs3);
+ exprAccessor.update(rhs3, Read);
+ }
+ /* fall-through */
+ case GIMPLE_BINARY_RHS:
+ {
+ const_tree rhs2 = gimple_assign_rhs2(s);
+ gcc_assert(rhs2);
+ exprAccessor.update(rhs2, Read);
+ }
+ /* fall-through */
+ case GIMPLE_UNARY_RHS:
+ case GIMPLE_SINGLE_RHS:
+ {
+ const_tree rhs1 = gimple_assign_rhs1(s);
+ exprAccessor.update(rhs1, Read);
+ const_tree lhs = gimple_assign_lhs(s);
+ if (!lhs) break;
+ exprAccessor.update(lhs, Write);
+ break;
+ }
+ default:
+ gcc_unreachable();
+ break;
+ }
+}
+
+void
+GimpleAccesser::_walk_pre(gcall *s)
+{
+ tree fndecl = gimple_call_fndecl(s);
+ unsigned n = gimple_call_num_args(s);
+ for (unsigned i = 0; i < n; i++)
+ {
+ const_tree a = gimple_call_arg(s, i);
+ gcc_assert(a);
+ exprAccessor.update(a, Read);
+ }
+
+ const_tree lhs = gimple_call_lhs(s);
+ if (!lhs) return;
+ exprAccessor.update(lhs, Write);
+}
+
+void
+GimpleAccesser::_walk_pre(greturn *s)
+{
+ const_tree val = gimple_return_retval(s);
+ if (!val) return;
+ exprAccessor.update(val, Read);
+}
+
+void
+GimpleAccesser::_walk_pre(gcond *s)
+{
+ const_tree lhs = gimple_cond_lhs(s);
+ const_tree rhs = gimple_cond_rhs(s);
+ gcc_assert(lhs && rhs);
+ exprAccessor.update(lhs, Read);
+ exprAccessor.update(rhs, Read);
+}
diff --git a/gcc/gimple-accesser.hpp b/gcc/gimple-accesser.hpp
new file mode 100644
index 00000000000..69bed4839a2
--- /dev/null
+++ b/gcc/gimple-accesser.hpp
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "gimple-walker.hpp"
+#include "expr-accessor.hpp"
+
+/*
+ * GimpleAccesser is intended to walk gimple
+ * and update a map that will hold information
+ * on whether a type was casted or not.
+ */
+class GimpleAccesser : public GimpleWalker
+{
+public:
+ GimpleAccesser() : GimpleWalker() {};
+ void print_accesses() { exprAccessor.print_accesses(); };
+private:
+ ExprAccessor exprAccessor;
+ virtual void _walk_pre(gcall *s) final;
+ virtual void _walk_pre(gassign *s) final;
+ virtual void _walk_pre(greturn *s) final;
+ virtual void _walk_pre(gcond *s) final;
+ // Do we need a glabel? I don't think so...
+ // But we might need a gswitch.
+};
diff --git a/gcc/gimple-caster.c b/gcc/gimple-caster.c
index 747d60920aa..299bbf6abfb 100644
--- a/gcc/gimple-caster.c
+++ b/gcc/gimple-caster.c
@@ -22,9 +22,68 @@ GimpleCaster::_walk_pre(gassign *s)
const_tree t_lhs = TREE_TYPE(lhs);
const_tree t_rhs = TREE_TYPE(rhs);
gcc_assert(t_lhs && t_rhs);
- const bool is_cast = equality.equal(t_lhs, t_rhs);
+ const bool is_cast = !equality.equal(t_lhs, t_rhs);
reason.is_escaping = is_cast;
reason.type_is_casted = is_cast;
exprEscaper.update(lhs, reason);
exprEscaper.update(rhs, reason);
+ // TODO:
+ // I think this will re-do the work... But it might be necessary?
+ GimpleEscaper::_walk_pre(s);
+}
+
+void
+GimpleCaster::_walk_pre(gcall *s)
+{
+ GimpleEscaper::_walk_pre(s);
+
+ const_tree fn = gimple_call_fndecl(s);
+ cgraph_node *node = cgraph_node::get(fn);
+ const bool known_function = GimpleEscaper::filter_known_function(node);
+ if (known_function) return;
+
+ const_tree f_t = TREE_TYPE(fn);
+ TypeIncompleteEquality equality;
+ TypeStringifier stringifier;
+
+ unsigned i = 0;
+ unsigned n = gimple_call_num_args(s);
+ for (tree a = TYPE_ARG_TYPES(f_t); NULL_TREE != a; a = TREE_CHAIN(a))
+ {
+ // There seems to be a final VOID_TYPE at the end of the chain
+ if (i == n) break;
+ const_tree formal_t = TREE_VALUE(a);
+ const_tree real = gimple_call_arg(s, i);
+ const_tree real_t = TREE_TYPE(real);
+ const bool is_casted = !equality.equal(formal_t, real_t);
+ const std::string name_r = stringifier.stringify(real_t);
+ const std::string name_f = stringifier.stringify(formal_t);
+ log("looking at casted argument %s == %s ? %s\n", name_r.c_str(), name_f.c_str(), is_casted ? "t" : "f");
+ Reason arg_reason;
+ arg_reason.is_escaping = is_casted;
+ arg_reason.type_is_casted = is_casted;
+ exprEscaper.update(real, arg_reason);
+ i++;
+ }
+
+ /*
+ unsigned n = gimple_call_num_args(s);
+ for (unsigned i = 0; i < n; i++)
+ {
+ const_tree a = gimple_call_arg(s, i);
+ gcc_assert(a);
+ exprEscaper.update(a, reason);
+ }
+ */
+
+ const_tree lhs = gimple_call_lhs(s);
+ if (!lhs) return;
+
+ const_tree r_t = TREE_TYPE(f_t);
+ const_tree l_t TREE_TYPE(lhs);
+ const bool is_casted = !equality.equal(r_t, l_t);
+ Reason ret_reason;
+ ret_reason.is_escaping = is_casted;
+ ret_reason.type_is_casted = is_casted;
+ exprEscaper.update(lhs, ret_reason);
}
diff --git a/gcc/gimple-caster.hpp b/gcc/gimple-caster.hpp
index 2495d537649..74086606862 100644
--- a/gcc/gimple-caster.hpp
+++ b/gcc/gimple-caster.hpp
@@ -12,9 +12,8 @@ class GimpleCaster : public GimpleEscaper
public:
GimpleCaster(ptrset_t &types) : GimpleEscaper(types) {};
private:
- // We don't need this from parent...
- virtual void _walk_pre(gcall *s) final {};
+ virtual void _walk_pre(gcall *s) final;
// Find out which structs are casted.
// Technically we could find this out on parent
- virtual void _walk_pre(gassign *s);
+ virtual void _walk_pre(gassign *s) final;
};
diff --git a/gcc/gimple-escaper.c b/gcc/gimple-escaper.c
index ed879123cc1..3f80d6cd868 100644
--- a/gcc/gimple-escaper.c
+++ b/gcc/gimple-escaper.c
@@ -175,7 +175,7 @@ GimpleEscaper::_walk_pre(gcond *s)
void
GimpleEscaper::_walk_pre(gcall *s)
{
- tree fn = gimple_call_fndecl(s);
+ const_tree fn = gimple_call_fndecl(s);
cgraph_node *node = cgraph_node::get(fn);
const bool _is_function_escaping = is_function_escaping(node);
const bool is_undefined = undefined.find(fn) != undefined.end();
@@ -186,7 +186,6 @@ GimpleEscaper::_walk_pre(gcall *s)
// TODO: Consider this...
//exprEscaper.update(fn, function_type_reason);
-
Reason arg_reason;
arg_reason.is_escaping = _is_escaping;
arg_reason.parameter_is_visible = _is_escaping;
diff --git a/gcc/gimple-escaper.hpp b/gcc/gimple-escaper.hpp
index b6f77111007..d589a3eec01 100644
--- a/gcc/gimple-escaper.hpp
+++ b/gcc/gimple-escaper.hpp
@@ -11,7 +11,7 @@ public:
ExprEscaper exprEscaper;
ptrset_t get_sets() { return exprEscaper.get_sets(); };
void print_reasons() { exprEscaper.print_reasons(); };
-private:
+protected:
typedef std::set<const_tree> undefset;
undefset undefined;
void _init();
diff --git a/gcc/gimple-walker.c b/gcc/gimple-walker.c
index 9259c0d9438..e61b49f0a98 100644
--- a/gcc/gimple-walker.c
+++ b/gcc/gimple-walker.c
@@ -60,7 +60,7 @@ GimpleWalker::walk()
cgraph_node *node = NULL;
FOR_EACH_FUNCTION_WITH_GIMPLE_BODY(node)
{
- // print_function(node);
+ print_function(node);
node->get_untransformed_body();
_walk_cnode(node);
}
diff --git a/gcc/ipa-prototype.h b/gcc/ipa-prototype.h
index 77413d5c218..a75efaa2e48 100644
--- a/gcc/ipa-prototype.h
+++ b/gcc/ipa-prototype.h
@@ -13,7 +13,7 @@ struct Reason {
Reason operator|(const Reason &);
Reason& operator|=(const Reason &);
void print() const;
- Reason() : is_escaping(0), global_is_visible(0), parameter_is_visible(0), type_is_casted(0), type_is_volatile(0), type_is_in_union(0) {};
+ Reason() : is_escaping(0), global_is_visible(0), parameter_is_visible(0), return_is_visible(0), type_is_casted(0), type_is_volatile(0), type_is_in_union(0) {};
};
diff --git a/gcc/ipa-type-escape-analysis.c b/gcc/ipa-type-escape-analysis.c
index 0f548bf4943..a88602054db 100644
--- a/gcc/ipa-type-escape-analysis.c
+++ b/gcc/ipa-type-escape-analysis.c
@@ -25,6 +25,7 @@
#include "gimple-collector.hpp"
#include "gimple-escaper.hpp"
#include "gimple-caster.hpp"
+#include "gimple-accesser.hpp"
static unsigned int iphw_execute();
@@ -104,8 +105,12 @@ collect_types()
GimpleEscaper gimpleEscaper(types);
gimpleEscaper.walk();
if (flag_print_escape_analysis) gimpleEscaper.print_reasons();
- types = gimpleEscaper.get_sets();
+ ptrset_t escaping = gimpleEscaper.get_sets();
GimpleCaster caster(types);
caster.walk();
if (flag_print_cast_analysis) caster.print_reasons();
+ ptrset_t casting = caster.get_sets();
+ GimpleAccesser accesser;
+ accesser.walk();
+ if (flag_print_access_analysis) accesser.print_accesses();
}
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 88f96ea3be4..390f73a6cc3 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
@@ -1,5 +1,5 @@
/* { dg-do link } */
-/* { dg-options "-flto -fipa-hello-world -fdump-ipa-hello-world" } */
+/* { dg-options "-fipa-type-escape-analysis -fdump-ipa-type-escape-analysis -fprint-access-analysis " } */
#include <stdio.h>
@@ -14,6 +14,5 @@ main ()
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" } } */
+// This means a read.
+/* { dg-final { scan-wpa-ipa-dump "astruct_s.a = 0x0001" "type-escape-analysis" } } */
diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-access-counter-01-simple-write-0.c b/gcc/testsuite/gcc.dg/ipa/ipa-access-counter-01-simple-write-0.c
index 6e7b3236294..d809ed31df8 100644
--- a/gcc/testsuite/gcc.dg/ipa/ipa-access-counter-01-simple-write-0.c
+++ b/gcc/testsuite/gcc.dg/ipa/ipa-access-counter-01-simple-write-0.c
@@ -1,5 +1,5 @@
/* { dg-do link } */
-/* { dg-options "-flto -fipa-hello-world -fdump-ipa-hello-world" } */
+/* { dg-options "-fipa-type-escape-analysis -fdump-ipa-type-escape-analysis -fprint-access-analysis " } */
#include <stdio.h>
@@ -14,6 +14,5 @@ main ()
astruct.a = 3;
}
-/* { dg-final { scan-wpa-ipa-dump "collected,astruct_s" "hello-world" } } */
-/* { dg-final { scan-wpa-ipa-dump "astruct_s.a write 1" "hello-world" } } */
-/* { dg-final { scan-wpa-ipa-dump "astruct_s.a write 2" "hello-world" } } */
+// This means that this is only a write and not a read.
+/* { dg-final { scan-wpa-ipa-dump "astruct_s.a = 0x0003" "type-escape-analysis" } } */
diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-access-counter-02-pointer-read-0.c b/gcc/testsuite/gcc.dg/ipa/ipa-access-counter-02-pointer-read-0.c
index 1b6755565ff..59f7707e5af 100644
--- a/gcc/testsuite/gcc.dg/ipa/ipa-access-counter-02-pointer-read-0.c
+++ b/gcc/testsuite/gcc.dg/ipa/ipa-access-counter-02-pointer-read-0.c
@@ -1,5 +1,5 @@
/* { dg-do link } */
-/* { dg-options "-flto -fipa-hello-world -fdump-ipa-hello-world" } */
+/* { dg-options "-fipa-type-escape-analysis -fdump-ipa-type-escape-analysis -fprint-access-analysis " } */
#include <stdio.h>
@@ -14,6 +14,5 @@ main ()
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" } } */
+// So, even if we have a pointer COMPONENT_REF counter still works...
+/* { dg-final { scan-wpa-ipa-dump "astruct_s.a = 0x0001" "type-escape-analysis" } } */
diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-access-counter-03-pointer-write-0.c b/gcc/testsuite/gcc.dg/ipa/ipa-access-counter-03-pointer-write-0.c
index 68e2f40a12a..17ad02529ee 100644
--- a/gcc/testsuite/gcc.dg/ipa/ipa-access-counter-03-pointer-write-0.c
+++ b/gcc/testsuite/gcc.dg/ipa/ipa-access-counter-03-pointer-write-0.c
@@ -1,5 +1,5 @@
/* { dg-do link } */
-/* { dg-options "-flto -fipa-hello-world -fdump-ipa-hello-world" } */
+/* { dg-options "-fipa-type-escape-analysis -fdump-ipa-type-escape-analysis -fprint-access-analysis " } */
#include <stdio.h>
@@ -14,6 +14,5 @@ main ()
astruct->a = 3;
}
-/* { dg-final { scan-wpa-ipa-dump "collected,astruct_s" "hello-world" } } */
-/* { dg-final { scan-wpa-ipa-dump "astruct_s.a write 1" "hello-world" } } */
-/* { dg-final { scan-wpa-ipa-dump "astruct_s.a write 2" "hello-world" } } */
+// This says that only writes are happening even if astruct is a pointer
+/* { dg-final { scan-wpa-ipa-dump "astruct_s.a = 0x0003" "type-escape-analysis" } } */
diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-access-counter-04-gimple-cond-0.c b/gcc/testsuite/gcc.dg/ipa/ipa-access-counter-04-gimple-cond-0.c
index 0dd152a2783..29f0fcfda4d 100644
--- a/gcc/testsuite/gcc.dg/ipa/ipa-access-counter-04-gimple-cond-0.c
+++ b/gcc/testsuite/gcc.dg/ipa/ipa-access-counter-04-gimple-cond-0.c
@@ -1,5 +1,5 @@
/* { dg-do link } */
-/* { dg-options "-flto -fipa-hello-world -fdump-ipa-hello-world" } */
+/* { dg-options "-fipa-type-escape-analysis -fdump-ipa-type-escape-analysis -fprint-access-analysis " } */
#include <stdio.h>
@@ -15,5 +15,5 @@ main ()
}
}
-/* { dg-final { scan-wpa-ipa-dump "collected,astruct_s" "hello-world" } } */
-/* { dg-final { scan-wpa-ipa-dump "astruct_s.a read 1" "hello-world" } } */
+// This says that astruct_s.a is read in a conditional
+/* { dg-final { scan-wpa-ipa-dump "astruct_s.a = 0x0001" "type-escape-analysis" } } */
diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-ea-16-parameter-cast-0.c b/gcc/testsuite/gcc.dg/ipa/ipa-ea-16-parameter-cast-0.c
new file mode 100644
index 00000000000..623a8c0af00
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/ipa-ea-16-parameter-cast-0.c
@@ -0,0 +1,20 @@
+/* { dg-do link } */
+/* { dg-options "-flto -fipa-type-escape-analysis -fdump-ipa-type-escape-analysis -fprint-cast-analysis -Wno-incompatible-pointer-types" } */
+
+#include <stddef.h>
+#include <stdio.h>
+
+struct astruct_s { _Bool a; _Bool b; _Bool c; };
+struct bstruct_s { _Bool a; _Bool b; _Bool c; };
+void foo(struct bstruct_s *s) { };
+
+int main(int argc, char** argv)
+{
+ struct astruct_s astruct;
+ foo(&astruct);
+}
+
+// This says that astruct_s is casted
+/* { dg-final { scan-wpa-ipa-dump " record astruct_s .boolean_type a;boolean_type b;boolean_type c;. reason: g=0 p=0 r=0 c=1 v=0 u=0" "type-escape-analysis" } } */
+// This says that the pointer is casted
+/* { dg-final { scan-wpa-ipa-dump " record astruct_s .boolean_type a;boolean_type b;boolean_type c;.. reason: g=0 p=0 r=0 c=1 v=0 u=0" "type-escape-analysis" } } */
diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-ea-17-malloc-0.c b/gcc/testsuite/gcc.dg/ipa/ipa-ea-17-malloc-0.c
new file mode 100644
index 00000000000..94e96701f96
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/ipa-ea-17-malloc-0.c
@@ -0,0 +1,17 @@
+/* { dg-do link } */
+/* { dg-options "-flto -fipa-type-escape-analysis -fdump-ipa-type-escape-analysis -fprint-cast-analysis -Wno-incompatible-pointer-types" } */
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+struct astruct_s { _Bool a; _Bool b; _Bool c; };
+
+int main(int argc, char** argv)
+{
+ struct astruct_s *a = malloc(sizeof(struct astruct_s));
+}
+
+// This says that astruct_s is not casted
+/* { dg-final { scan-wpa-ipa-dump " record astruct_s .boolean_type a;boolean_type b;boolean_type c;. reason: g=0 p=0 r=0 c=0 v=0 u=0" "type-escape-analysis" } } */
+/* { dg-final { scan-wpa-ipa-dump " record astruct_s .boolean_type a;boolean_type b;boolean_type c;.. reason: g=0 p=0 r=0 c=0 v=0 u=0" "type-escape-analysis" } } */
diff --git a/gcc/type-incomplete-equality.c b/gcc/type-incomplete-equality.c
index 9ce7eed1413..bf9047a98c7 100644
--- a/gcc/type-incomplete-equality.c
+++ b/gcc/type-incomplete-equality.c
@@ -44,9 +44,9 @@ TypeIncompleteEquality::_equal(const_tree l, const_tree r)
if (!valid_inputs) return l == r;
// if any of these are incomplete, then we can only compare using identifiers...
- const bool incomplete_l = is_incomplete(l);
- const bool incomplete_r = is_incomplete(r);
- const bool can_compare_structurally = incomplete_l && incomplete_r;
+ const bool complete_l = is_complete(l);
+ const bool complete_r = is_complete(r);
+ const bool can_compare_structurally = complete_l && complete_r;
if (can_compare_structurally) return TypeStructuralEquality::_equal(l, r);
const std::string n_l = TypeStringifier::get_type_identifier(l);
diff --git a/gcc/type-walker.c b/gcc/type-walker.c
index 54d547d3fd6..b79daef043d 100644
--- a/gcc/type-walker.c
+++ b/gcc/type-walker.c
@@ -260,7 +260,7 @@ TypeWalker::_walk_args(const_tree t)
{
for (tree arg_node = TYPE_ARG_TYPES(t); NULL_TREE != arg_node; arg_node = TREE_CHAIN(arg_node))
{
- tree arg_node_type = TREE_VALUE(arg_node);
+ const_tree arg_node_type = TREE_VALUE(arg_node);
gcc_assert(arg_node_type);
walk_arg(arg_node_type);
}