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? 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. 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 ----