summaryrefslogtreecommitdiff
path: root/gcc/ipa-type-escape-analysis.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ipa-type-escape-analysis.c')
-rw-r--r--gcc/ipa-type-escape-analysis.c321
1 files changed, 24 insertions, 297 deletions
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);