On Tue, 21 Jun 2016, Jeff Law wrote: > On 05/24/2016 03:14 AM, Richard Biener wrote: > > On Wed, 18 May 2016, Richard Biener wrote: > > > > > > > > The following adjusts get_alias_set beahvior when applied to > > > union accesses to use the union alias-set rather than alias-set > > > zero. This is in line with behavior from the alias oracle > > > which (bogously) circumvents alias-set zero with looking at > > > the alias-sets of the base object. Thus for > > > > > > union U { int i; float f; }; > > > > > > float > > > foo (union U *u, double *p) > > > { > > > u->f = 1.; > > > *p = 0; > > > return u->f; > > > } > > > > > > the langhooks ensured u->f has alias-set zero and thus disambiguation > > > against *p was not allowed. Still the alias-oracle did the disambiguation > > > by using the alias set of the union here (I think optimizing the > > > return to return 1. is valid). > > > > > > We have a good place in the middle-end to apply such rules which > > > is component_uses_parent_alias_set_from - this is where I move > > > the logic that is duplicated in various frontends. > > > > > > The Java and Ada frontends do not allow union type punning (LTO does), > > > so this patch may eventually pessimize them. I don't care anything > > > about Java but Ada folks might want to chime in. > > > > > > Bootstrapped on x86_64-unknown-linux-gnu, testing in progress. > > > > > > Ok for trunk? > > > > Ping. > > > > Thanks, > > Richard. > > > > > Thanks, > > > Richard. > > > > > > 2016-05-18 Richard Biener <rguent...@suse.de> > > > > > > * alias.c (component_uses_parent_alias_set_from): Handle > > > type punning through union accesses by using the union alias set. > > > * gimple.c (gimple_get_alias_set): Remove union type punning case. > > > > > > c-family/ > > > * c-common.c (c_common_get_alias_set): Remove union type punning case. > > > > > > fortran/ > > > * f95-lang.c (LANG_HOOKS_GET_ALIAS_SET): Remove (un-)define. > > > (gfc_get_alias_set): Remove. > You know the aliasing rules better than I. If you're confident using the > union's alias set is safe, then it's OK with me. > > My only worry is that if we get it wrong, it's likely to be a subtle bug that > may take a long time to expose itself. But that in and of itself shouldn't > stop us from going forward.
Ok, I have installed the patch now. I had to adjust g++.dg/torture/pr71002.C which was on the border of being invalid (it relied on us using alias-set zero for all union accesses). Basically it had union { struct A a; struct B a; } u; and accessed that memory using a type of struct C. The fix to the testcase is trivial, just put C into the union, the PR talks about that being difficult for the origin of the testcase as C is said to be not POD while the union type has to be. Still doesn't make it valid IMHO. Bootstrapped / tested on x86_64-unknown-linux-gnu, applied. Richard. 2016-06-29 Richard Biener <rguent...@suse.de> PR middle-end/71002 * alias.c (component_uses_parent_alias_set_from): Handle type punning through union accesses by using the union alias set. * gimple.c (gimple_get_alias_set): Remove union type punning case. c-family/ * c-common.c (c_common_get_alias_set): Remove union type punning case. fortran/ * f95-lang.c (LANG_HOOKS_GET_ALIAS_SET): Remove (un-)define. (gfc_get_alias_set): Remove. * g++.dg/torture/pr71002.C: Adjust testcase. Index: trunk/gcc/alias.c =================================================================== *** trunk.orig/gcc/alias.c 2016-05-18 11:15:41.744792403 +0200 --- trunk/gcc/alias.c 2016-05-18 11:31:40.139709782 +0200 *************** component_uses_parent_alias_set_from (co *** 619,624 **** --- 619,632 ---- case COMPONENT_REF: if (DECL_NONADDRESSABLE_P (TREE_OPERAND (t, 1))) found = t; + /* Permit type-punning when accessing a union, provided the access + is directly through the union. For example, this code does not + permit taking the address of a union member and then storing + through it. Even the type-punning allowed here is a GCC + extension, albeit a common and useful one; the C standard says + that such accesses have implementation-defined behavior. */ + else if (TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == UNION_TYPE) + found = t; break; case ARRAY_REF: Index: trunk/gcc/c-family/c-common.c =================================================================== *** trunk.orig/gcc/c-family/c-common.c 2016-05-18 11:15:41.744792403 +0200 --- trunk/gcc/c-family/c-common.c 2016-05-18 11:31:40.143709828 +0200 *************** static GTY(()) hash_table<c_type_hasher> *** 4734,4741 **** alias_set_type c_common_get_alias_set (tree t) { - tree u; - /* For VLAs, use the alias set of the element type rather than the default of alias set 0 for types compared structurally. */ if (TYPE_P (t) && TYPE_STRUCTURAL_EQUALITY_P (t)) --- 4734,4739 ---- *************** c_common_get_alias_set (tree t) *** 4745,4763 **** return -1; } - /* Permit type-punning when accessing a union, provided the access - is directly through the union. For example, this code does not - permit taking the address of a union member and then storing - through it. Even the type-punning allowed here is a GCC - extension, albeit a common and useful one; the C standard says - that such accesses have implementation-defined behavior. */ - for (u = t; - TREE_CODE (u) == COMPONENT_REF || TREE_CODE (u) == ARRAY_REF; - u = TREE_OPERAND (u, 0)) - if (TREE_CODE (u) == COMPONENT_REF - && TREE_CODE (TREE_TYPE (TREE_OPERAND (u, 0))) == UNION_TYPE) - return 0; - /* That's all the expressions we handle specially. */ if (!TYPE_P (t)) return -1; --- 4743,4748 ---- Index: trunk/gcc/fortran/f95-lang.c =================================================================== *** trunk.orig/gcc/fortran/f95-lang.c 2016-05-18 11:15:41.744792403 +0200 --- trunk/gcc/fortran/f95-lang.c 2016-05-18 11:31:48.623806334 +0200 *************** static bool global_bindings_p (void); *** 74,80 **** static bool gfc_init (void); static void gfc_finish (void); static void gfc_be_parse_file (void); - static alias_set_type gfc_get_alias_set (tree); static void gfc_init_ts (void); static tree gfc_builtin_function (tree); --- 74,79 ---- *************** static const struct attribute_spec gfc_a *** 110,116 **** #undef LANG_HOOKS_MARK_ADDRESSABLE #undef LANG_HOOKS_TYPE_FOR_MODE #undef LANG_HOOKS_TYPE_FOR_SIZE - #undef LANG_HOOKS_GET_ALIAS_SET #undef LANG_HOOKS_INIT_TS #undef LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE #undef LANG_HOOKS_OMP_PREDETERMINED_SHARING --- 109,114 ---- *************** static const struct attribute_spec gfc_a *** 142,148 **** #define LANG_HOOKS_PARSE_FILE gfc_be_parse_file #define LANG_HOOKS_TYPE_FOR_MODE gfc_type_for_mode #define LANG_HOOKS_TYPE_FOR_SIZE gfc_type_for_size - #define LANG_HOOKS_GET_ALIAS_SET gfc_get_alias_set #define LANG_HOOKS_INIT_TS gfc_init_ts #define LANG_HOOKS_OMP_PRIVATIZE_BY_REFERENCE gfc_omp_privatize_by_reference #define LANG_HOOKS_OMP_PREDETERMINED_SHARING gfc_omp_predetermined_sharing --- 140,145 ---- *************** gfc_init_decl_processing (void) *** 503,526 **** } - /* Return the typed-based alias set for T, which may be an expression - or a type. Return -1 if we don't do anything special. */ - - static alias_set_type - gfc_get_alias_set (tree t) - { - tree u; - - /* Permit type-punning when accessing an EQUIVALENCEd variable or - mixed type entry master's return value. */ - for (u = t; handled_component_p (u); u = TREE_OPERAND (u, 0)) - if (TREE_CODE (u) == COMPONENT_REF - && TREE_CODE (TREE_TYPE (TREE_OPERAND (u, 0))) == UNION_TYPE) - return 0; - - return -1; - } - /* Builtin function initialization. */ static tree --- 500,505 ---- Index: trunk/gcc/gimple.c =================================================================== *** trunk.orig/gcc/gimple.c 2016-05-18 11:15:41.744792403 +0200 --- trunk/gcc/gimple.c 2016-05-18 11:31:40.143709828 +0200 *************** gimple_signed_type (tree type) *** 2396,2416 **** alias_set_type gimple_get_alias_set (tree t) { - tree u; - - /* Permit type-punning when accessing a union, provided the access - is directly through the union. For example, this code does not - permit taking the address of a union member and then storing - through it. Even the type-punning allowed here is a GCC - extension, albeit a common and useful one; the C standard says - that such accesses have implementation-defined behavior. */ - for (u = t; - TREE_CODE (u) == COMPONENT_REF || TREE_CODE (u) == ARRAY_REF; - u = TREE_OPERAND (u, 0)) - if (TREE_CODE (u) == COMPONENT_REF - && TREE_CODE (TREE_TYPE (TREE_OPERAND (u, 0))) == UNION_TYPE) - return 0; - /* That's all the expressions we handle specially. */ if (!TYPE_P (t)) return -1; --- 2396,2401 ---- Index: gcc/testsuite/g++.dg/torture/pr71002.C =================================================================== --- gcc/testsuite/g++.dg/torture/pr71002.C (revision 237837) +++ gcc/testsuite/g++.dg/torture/pr71002.C (working copy) @@ -16,11 +16,6 @@ struct long_t char* pointer; }; -union long_raw_t { - unsigned char data[sizeof(long_t)]; - struct __attribute__((aligned(alignof(long_t)))) { } align; -}; - struct short_header { unsigned char is_short : 1; @@ -35,20 +30,20 @@ struct short_t union repr_t { - long_raw_t r; + long_t r; short_t s; const short_t& short_repr() const { return s; } const long_t& long_repr() const - { return *static_cast<const long_t*>(static_cast<const void*>(&r)); } + { return r; } short_t& short_repr() { return s; } long_t& long_repr() - { return *static_cast<long_t*>(static_cast<void*>(&r)); } + { return r; } }; class string