summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErick Ochoa <erick.ochoa@theobroma-systems.com>2020-05-14 16:00:00 +0200
committerErick Ochoa <erick.ochoa@theobroma-systems.com>2020-05-14 16:00:00 +0200
commita89b85cdcd75aa36836967894a99d24bbc37338a (patch)
tree8f646867cf5f1a404f5f0514ffec7ceb9790852d
parentcf730672e416091269ef355bd4a8be5cf2a23785 (diff)
Refactored code works in mcferick/type-escape-analysis-merge
-rw-r--r--gcc/ipa-escape-analysis.c32
-rw-r--r--gcc/ipa-escape-analysis.h5
-rw-r--r--gcc/ipa-str-reorg-dead-field-eliminate.c18
-rw-r--r--gcc/ipa-type-escape-analysis.c321
4 files changed, 60 insertions, 316 deletions
diff --git a/gcc/ipa-escape-analysis.c b/gcc/ipa-escape-analysis.c
index 04023a406a5..6c4e9105254 100644
--- a/gcc/ipa-escape-analysis.c
+++ b/gcc/ipa-escape-analysis.c
@@ -36,6 +36,8 @@
#include "collect-types.h"
#include "name-types.h"
+#include "ipa-escape-analysis.h"
+
//#define FUZZ_MODE 1
namespace type_playground {
@@ -290,6 +292,16 @@ collect_types_from_result_decl(const_tree expr, ptrset_t &types)
}
static void
+collect_types_from_function_decl(const_tree expr, ptrset_t &types)
+{
+ assert_is_type(expr, FUNCTION_DECL);
+ const_tree decl_type = TREE_TYPE(expr);
+ gcc_assert(decl_type);
+ // This will collect return, arguments and decl_type itself
+ collect_types(decl_type, types);
+}
+
+static void
collect_types_from_expr(const_tree expr, ptrset_t &types)
{
// These are the codes I saw using csmith to fuzz.
@@ -345,6 +357,9 @@ collect_types_from_expr(const_tree expr, ptrset_t &types)
case STRING_CST:
collect_types_from_string_cst(expr, types);
break;
+ case FUNCTION_DECL:
+ collect_types_from_function_decl(expr, types);
+ break;
default:
log("tree_code: %s\n", get_tree_code_name(code));
gcc_unreachable();
@@ -491,7 +506,8 @@ collect_types_from_stmt_return(gimple *stmt, ptrset_t &types)
{
is_gimple_code(stmt, GIMPLE_RETURN);
const_tree retval = gimple_return_retval(stmt);
- gcc_assert(retval);
+ if (!retval) return;
+
collect_types_from_expr(retval, types);
}
@@ -515,6 +531,8 @@ collect_types_from_stmt(gimple *stmt, ptrset_t &types)
break;
case GIMPLE_LABEL:
case GIMPLE_PREDICT:
+ case GIMPLE_DEBUG:
+ case GIMPLE_SWITCH:
#ifdef FUZZ_MODE
gcc_unreachable();
#endif
@@ -529,20 +547,14 @@ collect_types_from_stmt(gimple *stmt, ptrset_t &types)
}
}
+
static void
collect_types_from_cnode_decl(cgraph_node *cnode, ptrset_t &types)
{
gcc_assert(cnode);
const_tree decl = cnode->decl;
gcc_assert(decl);
- const_tree decl_type = TREE_TYPE(decl);
- gcc_assert(decl_type);
- function *func = DECL_STRUCT_FUNCTION (decl);
- gcc_assert(func);
- push_cfun(func);
- // This will collect return, arguments and decl_type itself
- collect_types(decl_type, types);
- pop_cfun();
+ collect_types_from_function_decl(decl, types);
}
static void
@@ -760,7 +772,7 @@ filter_out_types_in_set(ptrset_t &types)
}
-static void
+void
collect_types(ptrset_t &types)
{
collect_types_from_globals(types);
diff --git a/gcc/ipa-escape-analysis.h b/gcc/ipa-escape-analysis.h
new file mode 100644
index 00000000000..16611c2db56
--- /dev/null
+++ b/gcc/ipa-escape-analysis.h
@@ -0,0 +1,5 @@
+#pragma once
+
+#include "collect-types.h"
+
+void collect_types(ptrset_t &types);
diff --git a/gcc/ipa-str-reorg-dead-field-eliminate.c b/gcc/ipa-str-reorg-dead-field-eliminate.c
index f86ed1f866a..a3d20f64283 100644
--- a/gcc/ipa-str-reorg-dead-field-eliminate.c
+++ b/gcc/ipa-str-reorg-dead-field-eliminate.c
@@ -2705,15 +2705,15 @@ iphw_execute_escape_analysis()
gcc_assert(!flag_ipa_typelist_struct && !flag_ipa_typelist_field);
const record_field_set to_reorg = get_fields_to_reorg();
print_record_field_set(to_reorg);
- //separate_set_of_pairs_into_pair_of_sets(to_reorg, interesting_records, interesting_fields);
-
- //hash_set<const_tree> orig_type_map;
- //collect_orig_structs (orig_type_map);
- //t_map mod_type_map;
- //compute_modified_structs (orig_type_map, mod_type_map);
- //t_map inverse_type_map;
- //compute_inverse_type_map (mod_type_map, inverse_type_map);
- //rewrite_references_to_modified_structs (mod_type_map, inverse_type_map);
+ separate_set_of_pairs_into_pair_of_sets(to_reorg, interesting_records, interesting_fields);
+
+ hash_set<const_tree> orig_type_map;
+ collect_orig_structs (orig_type_map);
+ t_map mod_type_map;
+ compute_modified_structs (orig_type_map, mod_type_map);
+ t_map inverse_type_map;
+ compute_inverse_type_map (mod_type_map, inverse_type_map);
+ rewrite_references_to_modified_structs (mod_type_map, inverse_type_map);
}
static void
diff --git a/gcc/ipa-type-escape-analysis.c b/gcc/ipa-type-escape-analysis.c
index f4db0b6183f..368644912ca 100644
--- a/gcc/ipa-type-escape-analysis.c
+++ b/gcc/ipa-type-escape-analysis.c
@@ -31,6 +31,7 @@
#include "ipa-str-reorg-utils.h"
#include "ipa-type-escape-analysis.h"
+#include "ipa-escape-analysis.h"
// First we need to collect all types
@@ -242,42 +243,6 @@ filter_parm_declarations (const_tree parm_decl, type_map &escape_map)
return filter_type(escape_map, type);
}
-static void
-collect_global(type_map &escape_map, varpool_node *vnode)
-{
- log("collect_global\n");
- gcc_assert(vnode);
-
- struct ipa_ref *ref = NULL;
- for (int i = 0; vnode->iterate_referring (i, ref); i++)
- {
- log("inside vnode loop\n");
- tree decl = vnode->decl;
- gcc_assert(decl);
- enum tree_code code = TREE_CODE(decl);
- gcc_assert(VAR_DECL == code);
- bool filter_out = filter_var_decl(escape_map, decl);
- if (filter_out) continue;
-
- tree type = TREE_TYPE(decl);
- gcc_assert(type);
- log("collecting global type escape analysis %s\n", get_type_name(type));
- escaping_reason reason = new_escaping_reason();
- escaping_info info = { type, false, reason };
- escape_map.put (type, info);
- //escape_map.put (TYPE_MAIN_VARIANT(type), info);
- }
-}
-
-static void
-collect_globals(type_map &escape_map)
-{
- varpool_node *vnode;
- FOR_EACH_VARIABLE (vnode)
- {
- collect_global(escape_map, vnode);
- }
-}
static void
collect_parm_declarations (cgraph_node *cnode, type_map &escape_map)
@@ -300,266 +265,6 @@ collect_parm_declarations (cgraph_node *cnode, type_map &escape_map)
}
}
-static void
-collect_local_declarations (cgraph_node *cnode, type_map &escape_map)
-{
- gcc_assert(cnode);
- int i = 0;
- function *func = DECL_STRUCT_FUNCTION (cnode->decl);
- cnode->get_untransformed_body ();
- tree var_decl = NULL;
- FOR_EACH_LOCAL_DECL (func, i, var_decl)
- {
- gcc_assert(var_decl);
- bool filter_out = filter_var_decl(escape_map, var_decl);
- if (filter_out) continue;
-
- tree tree_type = TREE_TYPE(var_decl);
- gcc_assert(tree_type);
- escaping_reason reason = new_escaping_reason();
- escaping_info info = { tree_type, false, reason};
- escape_map.put(tree_type, info);
- }
-}
-
-static void collect_expr (const_tree expr, type_map &escape_map);
-
-static void
-collect_expr_in_component_ref(const_tree cref, type_map &escape_map)
-{
- gcc_assert(cref);
- const enum tree_code code = TREE_CODE(cref);
- const bool is_cref = COMPONENT_REF == code;
- gcc_assert(is_cref);
-
- const_tree _struct = TREE_OPERAND(cref, 0);
- gcc_assert(_struct);
-
- const_tree _struct_type = TREE_TYPE(_struct);
- log("we are in collect_expr_in_component_ref %s\n", get_type_name(_struct_type));
- escaping_reason reason = new_escaping_reason();
- escaping_info info = { _struct_type, false , reason};
- escape_map.put(_struct_type, info);
-
- collect_expr(_struct, escape_map);
-
-}
-
-static void
-collect_expr (const_tree expr, type_map &escape_map)
-{
- gcc_assert(expr);
- enum tree_code tree_code_expr = TREE_CODE(expr);
- switch (tree_code_expr)
- {
- case COMPONENT_REF:
- collect_expr_in_component_ref(expr, escape_map);
- break;
- default:
- break;
- }
-}
-
-static void
-collect_pointer_plus (tree lhs, tree rhs1, tree rhs2, type_map &escape_map)
-{
- log("collect_pointer_plus\n");
- const_tree lhs_type = lhs ? TREE_TYPE(lhs) : NULL;
- bool is_lhs_boring = lhs_type ? filter_type(escape_map, lhs_type) : true;
- const_tree rhs1_type = rhs1 ? TREE_TYPE(rhs1) : NULL;
- bool is_rhs1_boring = rhs1_type ? filter_type(escape_map, rhs1_type) : true;
- const_tree rhs2_type = rhs2 ? TREE_TYPE(rhs2) : NULL;
- bool is_rhs2_boring = rhs2_type ? filter_type(escape_map, rhs2_type) : true;
-
- if (!is_lhs_boring)
- {
- escaping_reason reason = new_escaping_reason();
- escaping_info info = { lhs_type , false, reason };
- escape_map.put(lhs_type, info);
- }
- if (!is_rhs1_boring)
- {
- collect_expr(rhs1, escape_map);
- }
- if (!is_rhs2_boring)
- {
- collect_expr(rhs2, escape_map);
- }
-}
-
-static void
-collect_assign_rhs (gimple *stmt, type_map &escape_map)
-{
- enum tree_code code = gimple_expr_code (stmt);
- switch (code)
- {
- case POINTER_PLUS_EXPR:
- case POINTER_DIFF_EXPR:
- case COMPONENT_REF:
- {
- tree rhs2 = gimple_assign_rhs2(stmt);
- tree rhs1 = gimple_assign_rhs1(stmt);
- tree lhs = gimple_assign_lhs (stmt);
- collect_pointer_plus (lhs, rhs1, rhs2, escape_map);
- break;
- }
- default:
- break;
- }
-}
-
-static void
-collect_assign (gimple *stmt, type_map &escape_map)
-{
- gcc_assert(stmt);
- collect_assign_rhs (stmt, escape_map);
-}
-
-static void
-collect_call_lhs (gimple *stmt, type_map &escape_map)
-{
- gcc_assert(stmt);
- tree lhs = gimple_call_lhs (stmt);
- if (!lhs) return;
-
- collect_expr (lhs, escape_map);
-}
-
-static void
-collect_call_rhs (gimple *stmt, type_map &escape_map)
-{
- gcc_assert(stmt);
- tree fn = gimple_call_fn (stmt);
-
- gcc_assert (fn);
- gcall *call = dyn_cast <gcall *> (stmt);
- //struct cgraph_node *n = cgraph_node::get (fn);
- //if (n) log ("collecting arguments for %s \n", n->name());
-
- tree return_type = gimple_call_return_type (call);
- bool is_return_type_boring = filter_type(escape_map, return_type);
-
- if (!is_return_type_boring) {
- escaping_reason reason = new_escaping_reason();
- escaping_info info = {return_type, false, reason};
- escape_map.put(return_type, info);
- }
-
- unsigned args = gimple_call_num_args (stmt);
- for (unsigned i = 0; i < args; i++)
- {
- tree arg = gimple_call_arg (stmt, i);
- tree arg_type = TREE_TYPE(arg);
- log("collecting argument of type %s\n", get_type_name(arg_type));
- bool is_arg_boring = filter_type(escape_map, arg_type);
- if (is_arg_boring) continue;
-
- escaping_reason reason = new_escaping_reason();
- escaping_info info = {arg_type, false, reason};
- escape_map.put(arg_type, info);
-
- }
-}
-
-static void
-collect_call(gimple *stmt, type_map &escape_map)
-{
- gcc_assert(stmt);
- collect_call_lhs (stmt, escape_map);
- collect_call_rhs (stmt, escape_map);
-}
-
-static void
-collect_stmt (gimple *stmt, type_map &escape_map)
-{
- gcc_assert (stmt);
- const enum gimple_code code = gimple_code (stmt);
- switch (code)
- {
- case GIMPLE_ASSIGN:
- collect_assign(stmt, escape_map);
- break;
- case GIMPLE_CALL:
- collect_call(stmt, escape_map);
- break;
- default:
- break;
- }
-
- return;
-}
-
-static void
-collect_basic_block (basic_block bb, type_map &escape_map)
-{
- gcc_assert(bb);
- for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next(&gsi))
- {
- gimple *stmt = gsi_stmt (gsi);
- collect_stmt (stmt, escape_map);
- }
-}
-
-static void
-collect_function_body (cgraph_node *cnode, type_map &escape_map)
-{
- gcc_assert (cnode);
- cnode->get_untransformed_body();
- basic_block bb = NULL;
- tree decl = cnode->decl;
- gcc_assert(decl);
- function *func = DECL_STRUCT_FUNCTION (decl);
- gcc_assert(func);
- push_cfun(func);
- FOR_EACH_BB_FN (bb, func)
- {
- gcc_assert(bb);
- collect_basic_block (bb, escape_map);
- }
- pop_cfun();
-}
-
-static void
-collect_return_type (cgraph_node *cnode, type_map &escape_map)
-{
- gcc_assert(cnode);
-
- const_tree decl = cnode->decl;
- const enum tree_code code = TREE_CODE(decl);
- const bool is_function_decl = FUNCTION_DECL == code;
- gcc_assert (is_function_decl);
-
- const_tree fn_type = TREE_TYPE (decl);
- const enum tree_code fn_type_code = TREE_CODE(fn_type);
- const bool is_fn_type = FUNCTION_TYPE == fn_type_code;
- gcc_assert (is_fn_type);
-
- const_tree ret_type = TREE_TYPE(fn_type);
- gcc_assert (ret_type);
-
- const bool is_boring = filter_type(escape_map, ret_type);
- if (is_boring) return;
-
- escaping_reason reason = new_escaping_reason();
- escaping_info info = {ret_type, false, reason};
- escape_map.put(ret_type, info);
- return;
-}
-
-static void
-collect_types(type_map &escape_map)
-{
- collect_globals(escape_map);
-
- cgraph_node *cnode = NULL;
- FOR_EACH_DEFINED_FUNCTION (cnode)
- {
- collect_function_body (cnode, escape_map);
- collect_local_declarations (cnode, escape_map);
- collect_parm_declarations (cnode, escape_map);
- collect_return_type (cnode, escape_map);
- }
-}
bool
_print_types( const_tree const &type, escaping_info *info, __attribute__((unused)) void*)
@@ -965,6 +670,26 @@ cast_to_void_in_program(type_map &escape_map)
}
}
+void
+ptrset_to_typemap(ptrset_t &ptrset, type_map &escape_map)
+{
+ // ptrset contains 3 sets
+ // a universe set (which arguably contains all trees)
+ // a points to record set (which contains trees which points to records)
+ // a complement set (which contains trees which are everything else)
+ // we need to put all trees from points to record set
+ // into the type_map
+ // we also want to create the info data structure...
+ for (auto i = ptrset.points_to_record.cbegin(); i != ptrset.points_to_record.cend(); ++i)
+ {
+ const_tree type = *i;
+ gcc_assert(type);
+ escaping_reason reason = new_escaping_reason();
+ escaping_info info = { type, false, reason };
+ escape_map.put(type, info);
+ }
+}
+
/* INFO:
* Yes, I know we are returning a std::map.
* Bad pattern? Maybe, but this will only be called once
@@ -979,7 +704,9 @@ cast_to_void_in_program(type_map &escape_map)
void
calculate_escaping_types(type_map &escape_map)
{
- collect_types(escape_map);
+ ptrset_t types;
+ collect_types(types);
+ ptrset_to_typemap(types, escape_map);
is_any_variable_escaping(escape_map);
is_any_function_escaping(escape_map);
cast_to_void_in_program(escape_map);