summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErick Ochoa <erick.ochoa@theobroma-systems.com>2020-03-10 10:26:58 +0100
committerErick Ochoa <erick.ochoa@theobroma-systems.com>2020-04-28 23:35:49 +0200
commit4d2dbb54bd00a4d32c417afbb86c73ff10be1d54 (patch)
tree0c67e684f3bcfff7b7162045e81d5c304523374b
parent4e178ad5cfa6c2e23b81537838458650251d435d (diff)
wip
-rw-r--r--gcc/ipa-hello-world.c163
1 files changed, 126 insertions, 37 deletions
diff --git a/gcc/ipa-hello-world.c b/gcc/ipa-hello-world.c
index 8289728f9bc..6d902a03ecf 100644
--- a/gcc/ipa-hello-world.c
+++ b/gcc/ipa-hello-world.c
@@ -27,6 +27,7 @@
#include "gimple.h"
#include "cfg.h" // needed for gimple-iterator.h
#include "gimple-iterator.h"
+#include <stdbool.h>
#include "ipa-str-reorg-utils.h"
@@ -43,15 +44,53 @@ log (const char * const format, ...)
}
-struct escaping_info_s { const_tree type; bool is_escaping; };
+struct escaping_reason_s {
+ unsigned global_is_visible : 1;
+ unsigned parameter_is_visible : 1;
+ unsigned return_is_visible : 1;
+ unsigned type_is_casted : 1;
+};
+typedef struct escaping_reason_s escaping_reason;
+
+struct escaping_info_s { const_tree type; bool is_escaping; escaping_reason reason; };
typedef struct escaping_info_s escaping_info;
typedef hash_map<const_tree, escaping_info> type_map;
static bool filter_type (type_map &escape_map, const_tree type);
-void update_escape_info (const_tree type, type_map &escape_map, bool is_escaping);
+void update_escape_info (const_tree type, type_map &escape_map, bool is_escaping, escaping_reason reason);
+
+static const escaping_reason null_reason = { 0, 0, 0, 0 };
+inline escaping_reason
+new_escaping_reason()
+{
+ return null_reason;
+}
+
+//TODO:
+// Should we be using C++?
+escaping_reason
+union_op(const escaping_reason &left, const escaping_reason &right)
+{
+ escaping_reason retval;
+ retval.global_is_visible = left.global_is_visible | right.global_is_visible;
+ retval.parameter_is_visible = left.parameter_is_visible | right.parameter_is_visible;
+ retval.return_is_visible = left.return_is_visible | right.return_is_visible;;
+ retval.type_is_casted = left.type_is_casted | right.type_is_casted;;
+ return retval;
+}
+
+void
+explain_print(escaping_reason reason)
+{
+ if (reason.global_is_visible) log("global is visible");
+ if (reason.parameter_is_visible) log(", parameter is visible");
+ if (reason.return_is_visible) log(", return is visible");
+ if (reason.type_is_casted) log(", type is casted");
+ log("\n");
+}
void
-update_escape_info_pointer (const_tree pointer_type, type_map &escape_map, bool is_escaping)
+update_escape_info_pointer (const_tree pointer_type, type_map &escape_map, bool is_escaping, escaping_reason reason)
{
gcc_assert(pointer_type);
enum tree_code tree_code_pointer_type = TREE_CODE(pointer_type);
@@ -62,13 +101,14 @@ update_escape_info_pointer (const_tree pointer_type, type_map &escape_map, bool
if (!info) return;
info->is_escaping |= is_escaping;
+ info->reason = union_op(info->reason, reason);
tree tree_type_pointer_type = TREE_TYPE(pointer_type);
gcc_assert(tree_type_pointer_type);
- update_escape_info (tree_type_pointer_type, escape_map, info->is_escaping);
+ update_escape_info (tree_type_pointer_type, escape_map, info->is_escaping, info->reason);
}
void
-update_escape_info_array (const_tree array_type, type_map &escape_map, bool is_escaping)
+update_escape_info_array (const_tree array_type, type_map &escape_map, bool is_escaping, escaping_reason reason)
{
gcc_assert(array_type);
enum tree_code tree_code_array_type = TREE_CODE(array_type);
@@ -79,13 +119,14 @@ update_escape_info_array (const_tree array_type, type_map &escape_map, bool is_e
if (!info) return;
info->is_escaping |= is_escaping;
+ info->reason = union_op(info->reason, reason);
tree tree_type_array_type = TREE_TYPE(array_type);
gcc_assert(tree_type_array_type);
- update_escape_info (tree_type_array_type, escape_map, info->is_escaping);
+ update_escape_info (tree_type_array_type, escape_map, info->is_escaping, info->reason);
}
void
-update_escape_info_record (const_tree record_type, type_map &escape_map, bool is_escaping)
+update_escape_info_record (const_tree record_type, type_map &escape_map, bool is_escaping, escaping_reason reason)
{
gcc_assert(record_type);
enum tree_code tree_code_record_type = TREE_CODE(record_type);
@@ -97,6 +138,7 @@ update_escape_info_record (const_tree record_type, type_map &escape_map, bool is
// it in the escaping info
gcc_assert(info);
info->is_escaping |= is_escaping;
+ info->reason = union_op(info->reason, reason);
for (tree field = TYPE_FIELDS (record_type); field; field = DECL_CHAIN (field))
@@ -104,28 +146,30 @@ update_escape_info_record (const_tree record_type, type_map &escape_map, bool is
gcc_assert(field);
tree tree_type_field = TREE_TYPE(field);
gcc_assert(tree_type_field);
- update_escape_info (tree_type_field, escape_map, info->is_escaping);
+ update_escape_info (tree_type_field, escape_map, info->is_escaping, info->reason);
}
}
void
-update_escape_info (const_tree type, type_map &escape_map, bool is_escaping)
+update_escape_info (const_tree type, type_map &escape_map, bool is_escaping, escaping_reason reason)
{
// INFO: This is an optimization.
if (!is_escaping) return;
gcc_assert(type);
enum tree_code tree_code_type = TREE_CODE(type);
+ // We need to make sure that we are only dealing with
+ // the main type and not typedefs...
switch (tree_code_type)
{
case ARRAY_TYPE:
- update_escape_info_array(type, escape_map, is_escaping);
+ update_escape_info_array(type, escape_map, is_escaping, reason);
break;
case POINTER_TYPE:
- update_escape_info_pointer(type, escape_map, is_escaping);
+ update_escape_info_pointer(type, escape_map, is_escaping, reason);
break;
case RECORD_TYPE:
- update_escape_info_record(type, escape_map, is_escaping);
+ update_escape_info_record(type, escape_map, is_escaping, reason);
break;
default:
break;
@@ -187,7 +231,8 @@ filter_type (type_map &escape_map, const_tree type)
if (retval) return retval;
- escaping_info info = { type, false };
+ escaping_reason reason = new_escaping_reason();
+ escaping_info info = { type , false , reason};
escape_map.put(type, info);
return retval;
}
@@ -234,7 +279,8 @@ collect_global(type_map &escape_map, varpool_node *vnode)
tree type = TREE_TYPE(decl);
gcc_assert(type);
- escaping_info info = { type, false };
+ escaping_reason reason = new_escaping_reason();
+ escaping_info info = { type, false, reason };
escape_map.put (type, info);
}
}
@@ -263,7 +309,9 @@ collect_parm_declarations (cgraph_node *cnode, type_map &escape_map)
log("putting parameter type %s\n", get_type_name(type));
gcc_assert(type);
- escaping_info info = { type, false };
+
+ escaping_reason reason = new_escaping_reason();
+ escaping_info info = { type, false, reason };
escape_map.put(type, info);
}
}
@@ -284,7 +332,8 @@ collect_local_declarations (cgraph_node *cnode, type_map &escape_map)
tree tree_type = TREE_TYPE(var_decl);
gcc_assert(tree_type);
- escaping_info info = { tree_type, false };
+ escaping_reason reason = new_escaping_reason();
+ escaping_info info = { tree_type, false, reason};
escape_map.put(tree_type, info);
}
}
@@ -296,22 +345,25 @@ collect_pointer_plus (tree lhs, tree rhs1, tree rhs2, type_map &escape_map)
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;
+ 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_info info = { lhs_type , false };
+ escaping_reason reason = new_escaping_reason();
+ escaping_info info = { lhs_type , false, reason };
escape_map.put(lhs_type, info);
}
if (!is_rhs1_boring)
{
- escaping_info info = { rhs1_type, false };
+ escaping_reason reason = new_escaping_reason();
+ escaping_info info = { rhs1_type, false , reason};
escape_map.put(rhs1_type, info);
}
if (!is_rhs2_boring)
{
- escaping_info info = {rhs2_type, false};
+ escaping_reason reason = new_escaping_reason();
+ escaping_info info = {rhs2_type, false, reason};
escape_map.put(rhs2_type, info);
}
}
@@ -410,7 +462,8 @@ _print_types( const_tree const &type, escaping_info *info, __attribute((unused))
{
log("collected,%s\n", get_type_name(type));
bool is_escaping = info->is_escaping;
- log("type %s is escaping %s\n", get_type_name(type), is_escaping ? "true" : "false");
+ log("type %s is escaping %s : ", get_type_name(type), is_escaping ? "true" : "false");
+ explain_print(info->reason);
return true;
}
@@ -429,14 +482,14 @@ is_variable_escaping(varpool_node *vnode)
}
static bool
-is_function_escaping(cgraph_node *cnode)
+is_function_escaping(const cgraph_node *cnode)
{
gcc_assert(cnode);
return cnode->externally_visible;
}
void
-calculate_escaping_parameters(cgraph_node *cnode, type_map &escape_map)
+calculate_escaping_parameters(const cgraph_node *cnode, type_map &escape_map)
{
gcc_assert(cnode);
tree function = cnode->decl;
@@ -455,13 +508,16 @@ calculate_escaping_parameters(cgraph_node *cnode, type_map &escape_map)
tree tree_type = TREE_TYPE(parm);
gcc_assert(tree_type);
// void update_escaping_info (const_tree type, type_map &escape_map, bool is_escaping);
- update_escape_info(tree_type, escape_map, is_escaping);
+
+ escaping_reason reason = new_escaping_reason();
+ reason.parameter_is_visible = is_escaping;
+ update_escape_info(tree_type, escape_map, is_escaping, reason);
log("variable %s is escaping %s\n", identifier, is_escaping ? "true" : "false");
}
}
void
-is_return_type_escaping(cgraph_node *cnode, type_map &escape_map)
+is_return_type_escaping(const cgraph_node *cnode, type_map &escape_map)
{
gcc_assert(cnode);
bool is_escaping = is_function_escaping(cnode);
@@ -478,26 +534,55 @@ is_return_type_escaping(cgraph_node *cnode, type_map &escape_map)
log("return type %s\n", get_type_name(return_type));
// void update_escaping_info (const_tree type, type_map &escape_map, bool is_escaping);
- update_escape_info(return_type, escape_map, is_escaping);
+/*struct escaping_reason_s {
+ unsigned global_is_visible : 1;
+ unsigned function_is_visible : 1;
+};
+*/
+ escaping_reason reason = new_escaping_reason();
+ reason.return_is_visible = is_escaping;
+ update_escape_info(return_type, escape_map, is_escaping, reason);
//escaping_info *info = escape_map.get(return_type);
// If there's no info it means it is not interesting...
//if (!info) return;
//info->is_escaping |= is_escaping;
}
+
+bool
+calculate_escaping_types_from_function_signatures (
+ cgraph_node * const &cnode, type_map *escape_map)
+{
+
+ gcc_assert(escape_map);
+ gcc_assert(cnode);
+ bool is_escaping = is_function_escaping(cnode);
+ log("function %s is escaping %s\n", cnode->name(), is_escaping ? "true" : "false");
+ calculate_escaping_parameters(cnode, *escape_map);
+ is_return_type_escaping(cnode, *escape_map);
+ return true;
+}
+
void
is_any_function_escaping(type_map &escape_map)
{
cgraph_node *cnode = NULL;
+ hash_set<cgraph_node *> not_defined_functions;
+
FOR_EACH_FUNCTION (cnode)
{
- cnode->get_untransformed_body();
- log("function name = %s\n", cnode->name());
- bool is_escaping = is_function_escaping(cnode);
- log("function %s is escaping %s\n", cnode->name(), is_escaping ? "true" : "false");
- calculate_escaping_parameters(cnode, escape_map);
- is_return_type_escaping(cnode, escape_map);
+ gcc_assert(cnode);
+ not_defined_functions.add(cnode);
+ }
+
+ FOR_EACH_DEFINED_FUNCTION(cnode)
+ {
+ gcc_assert(cnode);
+ cnode->get_untransformed_body();
+ not_defined_functions.remove(cnode);
}
+
+ not_defined_functions.traverse<type_map *, calculate_escaping_types_from_function_signatures> (&escape_map);
}
void
@@ -514,7 +599,9 @@ is_any_variable_escaping(type_map &escape_map)
tree type = TREE_TYPE(decl);
gcc_assert(type);
// void update_escaping_info (const_tree type, type_map &escape_map, bool is_escaping);
- update_escape_info (type, escape_map, is_escaping);
+ escaping_reason reason = new_escaping_reason();
+ reason.global_is_visible = is_escaping;
+ update_escape_info (type, escape_map, is_escaping, reason);
//escaping_info *info = escape_map.get(type);
//if (!info) return;
//info->is_escaping |= is_escaping;
@@ -549,15 +636,17 @@ cast_to_void_in_assign(const_tree lhs, const_tree rhs, type_map &escape_map)
log("lhs = %s, rhs = %s\n", type_name_lhs, type_name_rhs);
if (!is_var_decl_or_ssa_name) return;
- bool is_casting_stmt = tree_type_lhs != tree_type_rhs;
+ bool is_casting_stmt = TYPE_MAIN_VARIANT(tree_type_lhs) != TYPE_MAIN_VARIANT(tree_type_rhs);
log("is casting stmt ? %s\n", is_casting_stmt ? "true" : "false");
if (!is_casting_stmt) return;
log("escaping lhs %s\n", type_name_lhs);
- update_escape_info(tree_type_lhs, escape_map, true);
+ escaping_reason reason = new_escaping_reason();
+ reason.type_is_casted = is_casting_stmt;
+ update_escape_info(tree_type_lhs, escape_map, is_casting_stmt, reason);
log("escaping rhs %s\n", type_name_rhs);
- update_escape_info(tree_type_rhs, escape_map, true);
+ update_escape_info(tree_type_rhs, escape_map, is_casting_stmt, reason);
}
static void
@@ -632,7 +721,7 @@ static void
cast_to_void_in_program(type_map &escape_map)
{
cgraph_node *cnode = NULL;
- FOR_EACH_FUNCTION (cnode)
+ FOR_EACH_DEFINED_FUNCTION (cnode)
{
gcc_assert(cnode);
cnode->get_untransformed_body();