Hi, this patch implements cleanup we discussed some time ago on IRC. Instead of recording reference types in ipa-modref I record pointer types same way as done by RTL attributes and I moved corresponding logic to tree-ssa-alias.c. Problem is that it breaks some testcases:
./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr50444.c -O2 -flto -fno-use-linker-plugin -flto-partition=none (internal compiler error) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr50444.c -O2 -flto -fno-use-linker-plugin -flto-partition=none (test for excess errors) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr50444.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects (internal compiler error) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr50444.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects (test for excess errors) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr52419.c -O2 -flto -fno-use-linker-plugin -flto-partition=none (internal compiler error) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr52419.c -O2 -flto -fno-use-linker-plugin -flto-partition=none (test for excess errors) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr52419.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects (internal compiler error) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr52419.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects (test for excess errors) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr57748-1.c -O2 -flto -fno-use-linker-plugin -flto-partition=none (internal compiler error) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr57748-1.c -O2 -flto -fno-use-linker-plugin -flto-partition=none (test for excess errors) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr57748-1.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects (internal compiler error) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr57748-1.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects (test for excess errors) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr57748-2.c -O2 -flto -fno-use-linker-plugin -flto-partition=none (internal compiler error) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr57748-2.c -O2 -flto -fno-use-linker-plugin -flto-partition=none (test for excess errors) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr57748-2.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects (internal compiler error) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr57748-2.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects (test for excess errors) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr57748-3.c -O2 -flto -fno-use-linker-plugin -flto-partition=none (internal compiler error) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr57748-3.c -O2 -flto -fno-use-linker-plugin -flto-partition=none (test for excess errors) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr57748-3.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects (internal compiler error) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr57748-3.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects (test for excess errors) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr57748-4.c -O2 -flto -fno-use-linker-plugin -flto-partition=none (internal compiler error) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr57748-4.c -O2 -flto -fno-use-linker-plugin -flto-partition=none (test for excess errors) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr57748-4.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects (internal compiler error) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr57748-4.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects (test for excess errors) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr58041.c -O2 -flto -fno-use-linker-plugin -flto-partition=none (internal compiler error) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr58041.c -O2 -flto -fno-use-linker-plugin -flto-partition=none (test for excess errors) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr58041.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects (internal compiler error) ./testsuite/gcc/gcc.sum:FAIL: gcc.dg/torture/pr58041.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects (test for excess errors) I looked into first one and it is caused by "may_alias" attribute on the vector type. This makes build_pointer_type to set that it may alias all and the get_deref_alias_type return 0 while ao_ref_alias_set returns 4. I can live with this small loss of precision for ipa-modref, but I am using same logic in the ao_ref_compare for ipa-icf where we can not be conservative. I wonder how to fix this. One option is to keep the ipa-modref way of recording actual types that determine alias set rather pointers to them, but I recall you considered it confusing to have two sets of machineries for this. So perhaps we want to add a way to build pointer type ignoring may alias attribute? I see that RTL needs this to handle alias sets 0 because it also needs mathcing type size. I do not need that in TBAA machinery. Honza diff --git a/gcc/alias.c b/gcc/alias.c index f6d7a1791c4..0b12a89657e 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -737,7 +737,7 @@ get_deref_alias_set (tree t) adjusted to point to the outermost component reference that can be used for assigning an alias set. */ -tree +static tree reference_alias_ptr_type_1 (tree *t) { tree inner; diff --git a/gcc/alias.h b/gcc/alias.h index 807af957f02..4453d9723ce 100644 --- a/gcc/alias.h +++ b/gcc/alias.h @@ -36,7 +36,6 @@ extern int objects_must_conflict_p (tree, tree); extern int nonoverlapping_memrefs_p (const_rtx, const_rtx, bool); extern void dump_alias_stats_in_alias_c (FILE *s); tree reference_alias_ptr_type (tree); -tree reference_alias_ptr_type_1 (tree *); bool alias_ptr_types_compatible_p (tree, tree); int compare_base_decls (tree, tree); bool refs_same_for_tbaa_p (tree, tree); diff --git a/gcc/ipa-modref.c b/gcc/ipa-modref.c index 3f46bebed3c..a621b30b1e1 100644 --- a/gcc/ipa-modref.c +++ b/gcc/ipa-modref.c @@ -328,7 +328,7 @@ dump_lto_records (modref_records_lto *tt, FILE *out) fprintf (out, " Base %i:", (int)i); print_generic_expr (dump_file, n->base); fprintf (out, " (alias set %i)\n", - n->base ? get_alias_set (n->base) : 0); + n->base ? get_deref_alias_set (n->base) : 0); if (n->every_ref) { fprintf (out, " Every ref\n"); @@ -341,7 +341,7 @@ dump_lto_records (modref_records_lto *tt, FILE *out) fprintf (out, " Ref %i:", (int)j); print_generic_expr (dump_file, r->ref); fprintf (out, " (alias set %i)\n", - r->ref ? get_alias_set (r->ref) : 0); + r->ref ? get_deref_alias_set (r->ref) : 0); if (r->every_access) { fprintf (out, " Every access\n"); @@ -478,48 +478,18 @@ record_access (modref_records *tt, ao_ref *ref) static void record_access_lto (modref_records_lto *tt, ao_ref *ref) { - /* get_alias_set sometimes use different type to compute the alias set - than TREE_TYPE (base). Do same adjustments. */ tree base_type = NULL_TREE, ref_type = NULL_TREE; if (flag_strict_aliasing) { - tree base; - - base = ref->ref; - while (handled_component_p (base)) - base = TREE_OPERAND (base, 0); - - base_type = reference_alias_ptr_type_1 (&base); - - if (!base_type) - base_type = TREE_TYPE (base); - else - base_type = TYPE_REF_CAN_ALIAS_ALL (base_type) - ? NULL_TREE : TREE_TYPE (base_type); - - tree ref_expr = ref->ref; - ref_type = reference_alias_ptr_type_1 (&ref_expr); - - if (!ref_type) - ref_type = TREE_TYPE (ref_expr); - else - ref_type = TYPE_REF_CAN_ALIAS_ALL (ref_type) - ? NULL_TREE : TREE_TYPE (ref_type); - - /* Sanity check that we are in sync with what get_alias_set does. */ - gcc_checking_assert ((!base_type && !ao_ref_base_alias_set (ref)) - || get_alias_set (base_type) - == ao_ref_base_alias_set (ref)); - gcc_checking_assert ((!ref_type && !ao_ref_alias_set (ref)) - || get_alias_set (ref_type) - == ao_ref_alias_set (ref)); + base_type = ao_ref_base_alias_ptr_type (ref); + ref_type = ao_ref_alias_ptr_type (ref); /* Do not bother to record types that have no meaningful alias set. Also skip variably modified types since these go to local streams. */ - if (base_type && (!get_alias_set (base_type) + if (base_type && (!get_deref_alias_set (base_type) || variably_modified_type_p (base_type, NULL_TREE))) base_type = NULL_TREE; - if (ref_type && (!get_alias_set (ref_type) + if (ref_type && (!get_deref_alias_set (ref_type) || variably_modified_type_p (ref_type, NULL_TREE))) ref_type = NULL_TREE; } @@ -529,10 +499,10 @@ record_access_lto (modref_records_lto *tt, ao_ref *ref) fprintf (dump_file, " - Recording base type:"); print_generic_expr (dump_file, base_type); fprintf (dump_file, " (alias set %i) ref type:", - base_type ? get_alias_set (base_type) : 0); + base_type ? get_deref_alias_set (base_type) : 0); print_generic_expr (dump_file, ref_type); fprintf (dump_file, " (alias set %i) parm:%i\n", - ref_type ? get_alias_set (ref_type) : 0, + ref_type ? get_deref_alias_set (ref_type) : 0, a.parm_index); } @@ -1477,7 +1447,7 @@ read_modref_records (lto_input_block *ib, struct data_in *data_in, something obviously unnecessary. Do not glob types by alias sets; it is not 100% clear that ltrans types will get merged same way. Types may get refined based on ODR type conflicts. */ - if (base_tree && !get_alias_set (base_tree)) + if (base_tree && !get_deref_alias_set (base_tree)) { if (dump_file) { @@ -1490,7 +1460,7 @@ read_modref_records (lto_input_block *ib, struct data_in *data_in, if (nolto_ret) nolto_base_node = (*nolto_ret)->insert_base (base_tree - ? get_alias_set (base_tree) + ? get_deref_alias_set (base_tree) : 0); if (lto_ret) lto_base_node = (*lto_ret)->insert_base (base_tree); @@ -1509,7 +1479,7 @@ read_modref_records (lto_input_block *ib, struct data_in *data_in, { tree ref_tree = stream_read_tree (ib, data_in); - if (ref_tree && !get_alias_set (ref_tree)) + if (ref_tree && !get_deref_alias_set (ref_tree)) { if (dump_file) { @@ -1526,7 +1496,7 @@ read_modref_records (lto_input_block *ib, struct data_in *data_in, if (nolto_base_node) nolto_ref_node = nolto_base_node->insert_ref (ref_tree - ? get_alias_set (ref_tree) : 0, + ? get_deref_alias_set (ref_tree) : 0, max_refs); if (lto_base_node) lto_ref_node = lto_base_node->insert_ref (ref_tree, max_refs); diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index e64011d04df..b4719825167 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -739,6 +739,38 @@ ao_ref_alias_set (ao_ref *ref) return ref->ref_alias_set; } +/* Returns a type satisfying + get_deref_alias_set (type) == ao_ref_base_alias_set (REF). */ + +tree +ao_ref_base_alias_ptr_type (ao_ref *ref) +{ + tree base_ref; + + if (!ref->ref) + return NULL_TREE; + base_ref = ref->ref; + while (handled_component_p (base_ref)) + base_ref = TREE_OPERAND (base_ref, 0); + tree ret = reference_alias_ptr_type (base_ref); + gcc_checking_assert (get_deref_alias_set (ret) == ao_ref_base_alias_set (ref)); + return ret; +} + +/* Returns a type satisfying + get_deref_alias_set (type) == ao_ref_alias_set (REF). */ + +tree +ao_ref_alias_ptr_type (ao_ref *ref) +{ + if (!ref->ref) + return NULL_TREE; + tree ret = reference_alias_ptr_type (ref->ref); + gcc_checking_assert (get_deref_alias_set (ret) == ao_ref_alias_set (ref)); + return ret; +} + + /* Init an alias-oracle reference representation from a gimple pointer PTR a range specified by OFFSET, SIZE and MAX_SIZE under the assumption that RANGE_KNOWN is set. diff --git a/gcc/tree-ssa-alias.h b/gcc/tree-ssa-alias.h index 1561ead2941..830ac1bf84d 100644 --- a/gcc/tree-ssa-alias.h +++ b/gcc/tree-ssa-alias.h @@ -114,6 +114,8 @@ extern void ao_ref_init_from_ptr_and_size (ao_ref *, tree, tree); extern tree ao_ref_base (ao_ref *); extern alias_set_type ao_ref_alias_set (ao_ref *); extern alias_set_type ao_ref_base_alias_set (ao_ref *); +extern tree ao_ref_alias_ptr_type (ao_ref *); +extern tree ao_ref_base_alias_ptr_type (ao_ref *); extern bool ptr_deref_may_alias_global_p (tree); extern bool ptr_derefs_may_alias_p (tree, tree); extern bool ptrs_compare_unequal (tree, tree);