diff options
author | Erick Ochoa <erick.ochoa@theobroma-systems.com> | 2020-05-07 14:49:41 +0200 |
---|---|---|
committer | Erick Ochoa <erick.ochoa@theobroma-systems.com> | 2020-09-08 08:55:23 +0200 |
commit | 52b9adf126367a5d1bec100a4bb54226b23202cb (patch) | |
tree | 05debc3a58a5f93c64c73eb866acc29a0eda3e83 | |
parent | 8c6f1afdb762cb4635074c415712f2e2adf1b1b9 (diff) |
wip
-rwxr-xr-x | build.sh | 9 | ||||
-rw-r--r-- | gcc/Makefile.in | 1 | ||||
-rw-r--r-- | gcc/ipa-hello-world.c | 334 |
3 files changed, 301 insertions, 43 deletions
@@ -3,16 +3,11 @@ set -e set -u -installdir=${1:-"gcc-inst"} +installdir=${1:-"gcc-inst2"} mkdir -p $HOME/code/gcc-build/ mkdir -p $HOME/code/${installdir}/ pushd $HOME/code/gcc-build/ -if find . -mindepth 1 -print -quit 2>/dev/null | grep -q . ; then - echo "not empty?" -else - $OLDPWD/configure --disable-bootstrap --disable-libsanitizer --enable-__cxa_atexit --enable-shared --disable-libsanitizer --enable-languages=c,c++,fortran --enable-lto --enable-gold --enable-linker-build-id --with-cpu-emag --prefix="$HOME/code/${installdir}/" -fi - +$OLDPWD/configure --disable-bootstrap --disable-libsanitizer --enable-__cxa_atexit --enable-shared --disable-libsanitizer --enable-languages=c,c++,fortran --enable-lto --enable-gold --enable-linker-build-id --with-cpu-emag --prefix="$HOME/code/${installdir}/" make -j `nproc` make install -j `nproc` make check-gcc RUNTESTFLAGS="ipa.exp" diff --git a/gcc/Makefile.in b/gcc/Makefile.in index c55204ab129..5f5d41c49b7 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1410,6 +1410,7 @@ OBJS = \ internal-fn.o \ ipa-type-escape-analysis.o \ ipa-hello-world.o \ + compare-types.o \ ipa-cp.o \ ipa-sra.o \ ipa-devirt.o \ diff --git a/gcc/ipa-hello-world.c b/gcc/ipa-hello-world.c index 00e276a4bd7..d9af11cfb41 100644 --- a/gcc/ipa-hello-world.c +++ b/gcc/ipa-hello-world.c @@ -28,6 +28,9 @@ #include "gimple-iterator.h" #include "gimple-ssa.h" +#include "compare-types.h" +#include <set> + void inline log(const char* const fmt, ...) { @@ -39,57 +42,316 @@ log(const char* const fmt, ...) va_end(args); } +typedef std::set<const_tree> typeset; + +static const bool contains_record_types(const_tree type); + +static const bool +inner_type_contains_record_types(const_tree type) +{ + gcc_assert(type); + const_tree inner = TREE_TYPE(type); + return contains_record_types(inner); +} + +static const bool +pointer_contains_record_types(const_tree type) +{ + assert_is_type(type, POINTER_TYPE); + return inner_type_contains_record_types(type); +} + +static const bool +reference_contains_record_types(const_tree type) +{ + assert_is_type(type, REFERENCE_TYPE); + return inner_type_contains_record_types(type); +} + +static const bool +array_contains_record_types(const_tree type) +{ + assert_is_type(type, ARRAY_TYPE); + return inner_type_contains_record_types(type); +} + +static const bool +union_contains_record_types(const_tree type) +{ + assert_is_type(type, UNION_TYPE); + tree field = TYPE_FIELDS(type); + while (field) + { + const_tree field_type = TREE_TYPE(field); + gcc_assert(field_type); + const bool contains_record = contains_record_types(field_type); + if (contains_record) return true; + + field = DECL_CHAIN(field); + } + + return false; +} + +static const bool +function_or_method_contains_record_types(const_tree type) +{ + gcc_assert(type); + const_tree ret_type = TREE_TYPE(type); + const bool return_type_contains_record = contains_record_types(ret_type); + if (return_type_contains_record) return true; + + tree parm = TYPE_ARG_TYPES(type); + + while (parm) + { + const_tree parm_type = TREE_TYPE(parm); + const bool parm_type_contains_record = contains_record_types(parm_type); + if (parm_type) return true; + + parm = TREE_CHAIN(parm); + } + + return false; +} + +static const bool +function_contains_record_types(const_tree type) +{ + assert_is_type(type, FUNCTION_TYPE); + return function_or_method_contains_record_types(type); +} + +static const bool +method_contains_record_types(const_tree type) +{ + assert_is_type(type, FUNCTION_TYPE); + const_tree base_type = TYPE_METHOD_BASETYPE(type); + const bool base_type_contains_record_types = contains_record_types(base_type); + return base_type_contains_record_types && function_or_method_contains_record_types(type); +} + +static const bool +contains_record_types(const_tree type) +{ + gcc_assert(type); + const enum tree_code code = TREE_CODE(type); + if (code == RECORD_TYPE) return true; + + switch (code) + { + case VOID_TYPE: + case INTEGER_TYPE: + case REAL_TYPE: + case FIXED_POINT_TYPE: + case ENUMERAL_TYPE: + case BOOLEAN_TYPE: + case OFFSET_TYPE: + return false; + break; + default: + break; + } + + switch (code) + { + case POINTER_TYPE: + return pointer_contains_record_types(type); + break; + case REFERENCE_TYPE: + return reference_contains_record_types(type); + break; + case ARRAY_TYPE: + return array_contains_record_types(type); + break; + case UNION_TYPE: + return union_contains_record_types(type); + break; + case FUNCTION_TYPE: + return function_contains_record_types(type); + break; + case METHOD_TYPE: + return method_contains_record_types(type); + break; + case QUAL_UNION_TYPE: + case LANG_TYPE: + default: + gcc_unreachable(); + break; + } + + gcc_unreachable(); + return false; +} + static void -alias_experiment_gimple_body(const cgraph_node *cnode) +get_non_escaping_locals(const cgraph_node *cnode, typeset &escaping_types, typeset &non_escaping_types) { gcc_assert(cnode); - - function *func = DECL_STRUCT_FUNCTION(cnode->decl); - - // We are looking first into SSA becaues of - // this documentation... - // Points-to and escape analysis. - // Points-to analysis builds a set of constraints from the GIMPLE SSA IL - // representing all pointer operations and facts we do or do not know - // about pointers. Solving this set of constraints yields a conservatively - // correct solution for each pointer variable in the program (though we are - // only interested in SSA name pointers) as to what it may possibly point to. - // https://gcc.gnu.org/onlinedocs/gccint/Alias-analysis.html - - size_t j = 0; + function *func = DECL_STRUCT_FUNCTION (cnode->decl); + int i = 0; tree var_decl = NULL; - FOR_EACH_LOCAL_DECL(func, j, var_decl) + FOR_EACH_LOCAL_DECL(func, i, var_decl) { - const_tree identifier_node = DECL_NAME(var_decl); - if (!identifier_node) continue; - const char* const identifier_pointer = IDENTIFIER_POINTER(identifier_node); - log("var_decl = %s\n", identifier_pointer); - if (POINTER_TYPE_P(TREE_TYPE(var_decl))) break; + } +} + +static void +get_non_escaping_types(const cgraph_node *cnode, typeset &escaping_types, typeset &non_escaping_types) +{ + gcc_assert(cnode); + get_non_escaping_locals(cnode, escaping_types, non_escaping_types); +} - size_t i = 0; - tree ssa_name = NULL; - push_cfun(func); - FOR_EACH_SSA_NAME(i, ssa_name, cfun) +// So, have a set with TYPE_MAIN_VARIANTS... +typeset +get_non_escaping_types() +{ + cgraph_node *cnode = NULL; + typeset non_escaping_types; + typeset escaping_types; + FOR_EACH_FUNCTION_WITH_GIMPLE_BODY(cnode) { - struct ptr_info_def *pi = SSA_NAME_PTR_INFO(ssa_name); - if (!pi) continue; - log("i have a pi"); - pt_solution_includes(&pi->pt, var_decl); + cnode->get_untransformed_body(); + get_non_escaping_types(cnode, escaping_types, non_escaping_types); } - pop_cfun(); + return non_escaping_types; +} + +namespace test_type_equality { + +static void +test_main_variant() +{ + tree void_a = make_node(VOID_TYPE); + tree void_b = build_variant_type_copy(void_a); + const bool expected = true; + const bool observed = eq_types(void_a, void_b); + const bool success = expected == observed; + gcc_assert(success); +} + +static void +test_pointer_types_eq() +{ + tree pointer_a = make_node(POINTER_TYPE); + tree inner_type = make_node(INTEGER_TYPE); + TREE_TYPE(pointer_a) = inner_type; + tree pointer_b = build_variant_type_copy(pointer_a); + const bool expected = true; + const bool observed = eq_types(pointer_a, pointer_b); + const bool success = expected == observed; + gcc_assert(success); +} + +static void +test_pointer_types_ne() +{ + tree pointer_a = make_node(POINTER_TYPE); + tree inner_type_a = make_node(INTEGER_TYPE); + TREE_TYPE(pointer_a) = inner_type_a; + tree pointer_b = make_node(POINTER_TYPE); + tree inner_type_b = make_node(VOID_TYPE); + TREE_TYPE(pointer_b) = inner_type_b; + const bool expected = false; + const bool observed = eq_types(pointer_a, pointer_b, true); + const bool success = expected == observed; + gcc_assert(success); +} +static void +test_pointer_types_eq_structurally() +{ + tree pointer_a = make_node(POINTER_TYPE); + tree inner_type_a = make_node(INTEGER_TYPE); + TREE_TYPE(pointer_a) = inner_type_a; + tree pointer_b = make_node(POINTER_TYPE); + tree inner_type_b = make_node(INTEGER_TYPE); + TREE_TYPE(pointer_b) = inner_type_b; + const bool expected = true; + const bool observed = eq_types(pointer_a, pointer_b, true); + const bool success = expected == observed; + gcc_assert(success); +} + +static void +test_void_eq() +{ + tree void_a = make_node(VOID_TYPE); + tree void_b = build_variant_type_copy(void_a); + const bool expected = true; + const bool observed = eq_types(void_a, void_b, true); + const bool success = expected == observed; + gcc_assert(success); +} +static void +test_structural_equality_different_types() +{ + tree type_a = make_node(VOID_TYPE); + tree type_b = make_node(RECORD_TYPE); + const bool expected = false; + const bool observed = eq_types(type_a, type_b, true); + const bool success = expected == observed; + gcc_assert(success); +} + +static void +test_different_record_types() +{ + tree type_a = make_node(RECORD_TYPE); + tree type_b = make_node(RECORD_TYPE); + tree field_a = make_node(FIELD_DECL); + tree field_b = make_node(FIELD_DECL); + tree type_field_a = make_node(VOID_TYPE); + tree type_field_b = make_node(RECORD_TYPE); + TREE_TYPE(field_a) = type_field_a; + TREE_TYPE(field_b) = type_field_b; + TYPE_FIELDS(type_a) = field_a; + TYPE_FIELDS(type_b) = field_b; + const bool expected = false; + const bool observed = eq_types(type_a, type_b, true); + const bool success = expected == observed; + gcc_assert(success); } +static void +test_same_record_types() +{ + tree type_a = make_node(RECORD_TYPE); + tree field_a = make_node(FIELD_DECL); + tree type_field_a = make_node(VOID_TYPE); + TREE_TYPE(field_a) = type_field_a; + TYPE_FIELDS(type_a) = field_a; + tree type_b = build_variant_type_copy(type_a); + const bool expected = true; + const bool observed = eq_types(type_a, type_b, true); + const bool success = expected == observed; + gcc_assert(success); +} + +static void +run_tests() +{ + log("running tests...\n"); + test_main_variant(); + test_void_eq(); + test_structural_equality_different_types(); + test_different_record_types(); + test_same_record_types(); + test_pointer_types_eq_structurally(); + test_pointer_types_ne(); + test_pointer_types_eq(); + +} +} // test_type_equality + static unsigned int iphw_execute() { - cgraph_node *node = NULL; - FOR_EACH_FUNCTION_WITH_GIMPLE_BODY(node) - { - alias_experiment_gimple_body (node); - } + //test_type_equality::run_tests(); + typeset non_escaping = get_non_escaping_types(); return 0; } @@ -114,7 +376,7 @@ public: : simple_ipa_opt_pass(pass_data_ipa_hello_world, ctx) {} - virtual bool gate(function*) { return flag_ipa_hello_world; } + virtual bool gate(function*) { return false; } virtual unsigned execute (function*) { return iphw_execute(); } }; } // anon namespace |