diff options
Diffstat (limited to 'gcc/ipa-type-escape-analysis.c')
-rw-r--r-- | gcc/ipa-type-escape-analysis.c | 321 |
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); |