Re: [PATCH] Work around host compiler placement new aliasing bug
Richard Biener wrote: On Wed, Jul 29, 2015 at 3:57 PM, Ulrich Weigand uweig...@de.ibm.com wrote: Hello, this patch is a workaround for the problem discussed here: https://gcc.gnu.org/ml/gcc-patches/2015-07/msg01597.html The problem is that the new pool allocator code relies on C++ aliasing rules related to placement new (basically, that placement new changes the dynamic type of the referenced memory). GCC compilers prior to version 4.3 did not implement this rule correctly (PR 29286). When building current GCC with a host compiler that is affected by this bug, and we build with optimization enabled (this typically only happens when building a cross-compiler), the resulting compiler binary may be miscompiled. The patch below attempts to detect this situation by checking whether the host compiler is a version of GCC prior to 4.3 (but stil accepts the -fno-strict-aliasing flag). If so, -fno-strict-aliasing is added to the flags when building the compiler binary. Tested on i686-linux, and when building an SPU cross-compiler using a gcc 4.1 powerpc64-linux host compiler. OK for mainline? Ok if nobody objects. I've checked this in now. Thanks, Ulrich -- Dr. Ulrich Weigand GNU/Linux compilers and toolchain ulrich.weig...@de.ibm.com
[PATCH] Work around host compiler placement new aliasing bug
Hello, this patch is a workaround for the problem discussed here: https://gcc.gnu.org/ml/gcc-patches/2015-07/msg01597.html The problem is that the new pool allocator code relies on C++ aliasing rules related to placement new (basically, that placement new changes the dynamic type of the referenced memory). GCC compilers prior to version 4.3 did not implement this rule correctly (PR 29286). When building current GCC with a host compiler that is affected by this bug, and we build with optimization enabled (this typically only happens when building a cross-compiler), the resulting compiler binary may be miscompiled. The patch below attempts to detect this situation by checking whether the host compiler is a version of GCC prior to 4.3 (but stil accepts the -fno-strict-aliasing flag). If so, -fno-strict-aliasing is added to the flags when building the compiler binary. Tested on i686-linux, and when building an SPU cross-compiler using a gcc 4.1 powerpc64-linux host compiler. OK for mainline? Bye, Ulrich gcc/ChangeLog: * configure.ac: Set aliasing_flags to -fno-strict-aliasing if the host compiler is affected by placement new aliasing bug. * configure: Regenerate. * Makefile.in (ALIASING_FLAGS): New variable. (ALL_CXXFLAGS): Add $(ALIASING_FLAGS). Index: gcc/configure === --- gcc/configure (revision 226312) +++ gcc/configure (working copy) @@ -789,6 +789,7 @@ c_strict_warn strict_warn c_loose_warn loose_warn +aliasing_flags CPP EGREP GREP @@ -6526,6 +6527,42 @@ fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi +# Check whether compiler is affected by placement new aliasing bug (PR 29286). +# If the host compiler is affected by the bug, and we build with optimization +# enabled (which happens e.g. when cross-compiling), the pool allocator may +# get miscompiled. Use -fno-strict-aliasing to work around this problem. +# Since there is no reliable feature check for the presence of this bug, +# we simply use a GCC version number check. (This should never trigger for +# stages 2 or 3 of a native bootstrap.) +aliasing_flags= +if test $GCC = yes; then + saved_CXXFLAGS=$CXXFLAGS + + # The following test compilation will succeed if and only if $CXX accepts + # -fno-strict-aliasing *and* is older than GCC 4.3. + CXXFLAGS=$CXXFLAGS -fno-strict-aliasing + { $as_echo $as_me:${as_lineno-$LINENO}: checking whether $CXX is affected by placement new aliasing bug 5 +$as_echo_n checking whether $CXX is affected by placement new aliasing bug... 6; } + cat confdefs.h - _ACEOF conftest.$ac_ext +/* end confdefs.h. */ + +#if (__GNUC__ 4) || (__GNUC__ == 4 __GNUC_MINOR__ = 3) +#error compiler not affected by placement new aliasing bug +#endif + +_ACEOF +if ac_fn_cxx_try_compile $LINENO; then : + { $as_echo $as_me:${as_lineno-$LINENO}: result: yes 5 +$as_echo yes 6; }; aliasing_flags='-fno-strict-aliasing' +else + { $as_echo $as_me:${as_lineno-$LINENO}: result: no 5 +$as_echo no 6; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + CXXFLAGS=$saved_CXXFLAGS +fi + @@ -18301,7 +18338,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat conftest.$ac_ext _LT_EOF -#line 18304 configure +#line 18341 configure #include confdefs.h #if HAVE_DLFCN_H @@ -18407,7 +18444,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat conftest.$ac_ext _LT_EOF -#line 18410 configure +#line 18447 configure #include confdefs.h #if HAVE_DLFCN_H Index: gcc/configure.ac === --- gcc/configure.ac(revision 226312) +++ gcc/configure.ac(working copy) @@ -416,6 +416,32 @@ struct Xlong long { typedef long long ]], [[Xint64_t::t x;]])],[],[AC_MSG_ERROR([error verifying int64_t uses long long])]) fi +# Check whether compiler is affected by placement new aliasing bug (PR 29286). +# If the host compiler is affected by the bug, and we build with optimization +# enabled (which happens e.g. when cross-compiling), the pool allocator may +# get miscompiled. Use -fno-strict-aliasing to work around this problem. +# Since there is no reliable feature check for the presence of this bug, +# we simply use a GCC version number check. (This should never trigger for +# stages 2 or 3 of a native bootstrap.) +aliasing_flags= +if test $GCC = yes; then + saved_CXXFLAGS=$CXXFLAGS + + # The following test compilation will succeed if and only if $CXX accepts + # -fno-strict-aliasing *and* is older than GCC 4.3. + CXXFLAGS=$CXXFLAGS -fno-strict-aliasing + AC_MSG_CHECKING([whether $CXX is affected by placement new aliasing bug]) + AC_COMPILE_IFELSE([ +#if (__GNUC__ 4) || (__GNUC__ == 4 __GNUC_MINOR__ = 3) +#error compiler not affected by placement new aliasing bug +#endif +], +[AC_MSG_RESULT([yes]); aliasing_flags
Re: [PATCH] Work around host compiler placement new aliasing bug
On Wed, Jul 29, 2015 at 3:57 PM, Ulrich Weigand uweig...@de.ibm.com wrote: Hello, this patch is a workaround for the problem discussed here: https://gcc.gnu.org/ml/gcc-patches/2015-07/msg01597.html The problem is that the new pool allocator code relies on C++ aliasing rules related to placement new (basically, that placement new changes the dynamic type of the referenced memory). GCC compilers prior to version 4.3 did not implement this rule correctly (PR 29286). When building current GCC with a host compiler that is affected by this bug, and we build with optimization enabled (this typically only happens when building a cross-compiler), the resulting compiler binary may be miscompiled. The patch below attempts to detect this situation by checking whether the host compiler is a version of GCC prior to 4.3 (but stil accepts the -fno-strict-aliasing flag). If so, -fno-strict-aliasing is added to the flags when building the compiler binary. Tested on i686-linux, and when building an SPU cross-compiler using a gcc 4.1 powerpc64-linux host compiler. OK for mainline? Ok if nobody objects. Thanks, Richard. Bye, Ulrich gcc/ChangeLog: * configure.ac: Set aliasing_flags to -fno-strict-aliasing if the host compiler is affected by placement new aliasing bug. * configure: Regenerate. * Makefile.in (ALIASING_FLAGS): New variable. (ALL_CXXFLAGS): Add $(ALIASING_FLAGS). Index: gcc/configure === --- gcc/configure (revision 226312) +++ gcc/configure (working copy) @@ -789,6 +789,7 @@ c_strict_warn strict_warn c_loose_warn loose_warn +aliasing_flags CPP EGREP GREP @@ -6526,6 +6527,42 @@ fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi +# Check whether compiler is affected by placement new aliasing bug (PR 29286). +# If the host compiler is affected by the bug, and we build with optimization +# enabled (which happens e.g. when cross-compiling), the pool allocator may +# get miscompiled. Use -fno-strict-aliasing to work around this problem. +# Since there is no reliable feature check for the presence of this bug, +# we simply use a GCC version number check. (This should never trigger for +# stages 2 or 3 of a native bootstrap.) +aliasing_flags= +if test $GCC = yes; then + saved_CXXFLAGS=$CXXFLAGS + + # The following test compilation will succeed if and only if $CXX accepts + # -fno-strict-aliasing *and* is older than GCC 4.3. + CXXFLAGS=$CXXFLAGS -fno-strict-aliasing + { $as_echo $as_me:${as_lineno-$LINENO}: checking whether $CXX is affected by placement new aliasing bug 5 +$as_echo_n checking whether $CXX is affected by placement new aliasing bug... 6; } + cat confdefs.h - _ACEOF conftest.$ac_ext +/* end confdefs.h. */ + +#if (__GNUC__ 4) || (__GNUC__ == 4 __GNUC_MINOR__ = 3) +#error compiler not affected by placement new aliasing bug +#endif + +_ACEOF +if ac_fn_cxx_try_compile $LINENO; then : + { $as_echo $as_me:${as_lineno-$LINENO}: result: yes 5 +$as_echo yes 6; }; aliasing_flags='-fno-strict-aliasing' +else + { $as_echo $as_me:${as_lineno-$LINENO}: result: no 5 +$as_echo no 6; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + CXXFLAGS=$saved_CXXFLAGS +fi + @@ -18301,7 +18338,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat conftest.$ac_ext _LT_EOF -#line 18304 configure +#line 18341 configure #include confdefs.h #if HAVE_DLFCN_H @@ -18407,7 +18444,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat conftest.$ac_ext _LT_EOF -#line 18410 configure +#line 18447 configure #include confdefs.h #if HAVE_DLFCN_H Index: gcc/configure.ac === --- gcc/configure.ac(revision 226312) +++ gcc/configure.ac(working copy) @@ -416,6 +416,32 @@ struct Xlong long { typedef long long ]], [[Xint64_t::t x;]])],[],[AC_MSG_ERROR([error verifying int64_t uses long long])]) fi +# Check whether compiler is affected by placement new aliasing bug (PR 29286). +# If the host compiler is affected by the bug, and we build with optimization +# enabled (which happens e.g. when cross-compiling), the pool allocator may +# get miscompiled. Use -fno-strict-aliasing to work around this problem. +# Since there is no reliable feature check for the presence of this bug, +# we simply use a GCC version number check. (This should never trigger for +# stages 2 or 3 of a native bootstrap.) +aliasing_flags= +if test $GCC = yes; then + saved_CXXFLAGS=$CXXFLAGS + + # The following test compilation will succeed if and only if $CXX accepts + # -fno-strict-aliasing *and* is older than GCC 4.3. + CXXFLAGS=$CXXFLAGS -fno-strict-aliasing + AC_MSG_CHECKING([whether $CXX
Re: [PATCH] Fix PR 48981 aliasing bug inside GCC
On Thu, May 26, 2011 at 11:56 PM, Andrew Pinski pins...@gmail.com wrote: The problem here is that vec.c accesses VEC_type_base via a vec_prefix but VEC_type_base's first field is not a vec_prefix. This patch fixes the problem by changing how VEC_*_base is done by using vec_prefix as the real base. OK? Bootstrapped and tested on x86_64 without any regressions. Ok. Thanks for fixing this! Richard. Thanks, Andrew Pinski ChangeLog: * gengtype.c (vec_prefix_type): New function. (note_def_vec): Use vec_prefix_type and change the length attribute to be based on the prefix. * vec.c: Include coretypes.h before vec.h. (struct vec_prefix): Remove. (vec_gc_p_reserve): Change the offsetof to sizeof. (vec_gc_p_reserve_exact): Likewise. (vec_heap_p_reserve): Likewise. (vec_heap_p_reserve_exact): Likewise. (vec_stack_o_reserve_1): Copy from +1 instead of from vec. (vec_stack_p_reserve): Change the offsetof to sizeof. (vec_stack_p_reserve_exact): Likewise. * vec.h (struct vec_prefix): New struct definition. (VEC_T(T,B)): Use vec_prefix instead of having num/alloc fields. (VEC_T_GTY(T,B)): Likewise. (DEF_VEC_FUNC_P(T)): Use prefix field. (DEF_VEC_NONALLOC_FUNCS_O(T,A)): Likewise. (DEF_VEC_NONALLOC_FUNCS_I(T,A)): Likewise.
[PATCH] Fix PR 48981 aliasing bug inside GCC
The problem here is that vec.c accesses VEC_type_base via a vec_prefix but VEC_type_base's first field is not a vec_prefix. This patch fixes the problem by changing how VEC_*_base is done by using vec_prefix as the real base. OK? Bootstrapped and tested on x86_64 without any regressions. Thanks, Andrew Pinski ChangeLog: * gengtype.c (vec_prefix_type): New function. (note_def_vec): Use vec_prefix_type and change the length attribute to be based on the prefix. * vec.c: Include coretypes.h before vec.h. (struct vec_prefix): Remove. (vec_gc_p_reserve): Change the offsetof to sizeof. (vec_gc_p_reserve_exact): Likewise. (vec_heap_p_reserve): Likewise. (vec_heap_p_reserve_exact): Likewise. (vec_stack_o_reserve_1): Copy from +1 instead of from vec. (vec_stack_p_reserve): Change the offsetof to sizeof. (vec_stack_p_reserve_exact): Likewise. * vec.h (struct vec_prefix): New struct definition. (VEC_T(T,B)): Use vec_prefix instead of having num/alloc fields. (VEC_T_GTY(T,B)): Likewise. (DEF_VEC_FUNC_P(T)): Use prefix field. (DEF_VEC_NONALLOC_FUNCS_O(T,A)): Likewise. (DEF_VEC_NONALLOC_FUNCS_I(T,A)): Likewise. Index: gengtype.c === --- gengtype.c (revision 174305) +++ gengtype.c (working copy) @@ -4130,14 +4130,36 @@ write_roots (pair_p variables, bool emit finish_root_table (flp, pch_rs, LAST_GGC_ROOT_TAB, ggc_root_tab, gt_pch_scalar_rtab); } +/* Record the definition of the vec_prefix structure, as defined in vec.h: + + struct vec_prefix GTY(()) { + unsigned num; + unsigned alloc; + }; */ +static type_p +vec_prefix_type (void) +{ + static type_p prefix_type = NULL; + if (prefix_type == NULL) +{ + pair_p fields; + static struct fileloc pos = { NULL, 0 }; + type_p len_ty = create_scalar_type (unsigned); + pos.file = input_file_by_name (__FILE__); pos.line = __LINE__; + fields = create_field_at (0, len_ty, alloc, 0, pos); + fields = create_field_at (fields, len_ty, num, 0, pos); + prefix_type = new_structure (vec_prefix, 0, pos, fields, 0); + prefix_type-u.s.bitmap = -1; +} + return prefix_type; +} /* Record the definition of a generic VEC structure, as if we had expanded the macros in vec.h: typedef struct VEC_type_base GTY(()) { - unsigned num; - unsigned alloc; - type GTY((length (%h.num))) vec[1]; + struct vec_prefix prefix; + type GTY((length (%h.prefix.num))) vec[1]; } VEC_type_base where the GTY(()) tags are only present if is_scalar is _false_. */ @@ -4148,7 +4170,6 @@ note_def_vec (const char *type_name, boo pair_p fields; type_p t; options_p o; - type_p len_ty = create_scalar_type (unsigned); const char *name = concat (VEC_, type_name, _base, (char *) 0); if (is_scalar) @@ -4159,12 +4180,11 @@ note_def_vec (const char *type_name, boo else { t = resolve_typedef (type_name, pos); - o = create_string_option (0, length, %h.num); + o = create_string_option (0, length, %h.prefix.num); } /* We assemble the field list in reverse order. */ fields = create_field_at (0, create_array (t, 1), vec, o, pos); - fields = create_field_at (fields, len_ty, alloc, 0, pos); - fields = create_field_at (fields, len_ty, num, 0, pos); + fields = create_field_at (fields, vec_prefix_type (), prefix, 0, pos); do_typedef (name, new_structure (name, 0, pos, fields, 0), pos); } Index: vec.c === --- vec.c (revision 174305) +++ vec.c (working copy) @@ -28,20 +28,12 @@ along with GCC; see the file COPYING3. #endif #include system.h +#include coretypes.h #include ggc.h #include vec.h -#include coretypes.h #include diagnostic-core.h #include hashtab.h -struct vec_prefix -{ - unsigned num; - unsigned alloc; - void *vec[1]; -}; - - #ifdef GATHER_STATISTICS /* Store information about each particular vector. */ @@ -254,7 +246,7 @@ void * vec_gc_p_reserve (void *vec, int reserve MEM_STAT_DECL) { return vec_gc_o_reserve_1 (vec, reserve, -offsetof (struct vec_prefix, vec), +sizeof (struct vec_prefix), sizeof (void *), false PASS_MEM_STAT); } @@ -268,7 +260,7 @@ void * vec_gc_p_reserve_exact (void *vec, int reserve MEM_STAT_DECL) { return vec_gc_o_reserve_1 (vec, reserve, -offsetof (struct vec_prefix, vec), +sizeof (struct vec_prefix), sizeof (void *), true PASS_MEM_STAT); } @@ -337,7 +329,7 @@ void * vec_heap_p_reserve (void *vec, int reserve MEM_STAT_DECL) { return vec_heap_o_reserve_1 (vec, reserve, - offsetof (struct vec_prefix, vec), + sizeof (struct vec_prefix), sizeof (void *),
Re: old aliasing bug: fixed?
On Thu, Sep 30, 2010 at 5:39 AM, Richard Guenther richard.guent...@gmail.com wrote: On Thu, Sep 30, 2010 at 9:54 AM, Albert Cahalan acaha...@gmail.com wrote: int weird(float *fp){ // access an int as an int (see caller), // so not an aliasing violation return *(int*)fp; } int main(int argc, char *argv[]){ return weird((float*)argc); } I just tried this code with gcc 4.4.5 on 32-bit powerpc using -O2 -W -Wall. Assembly code for the weird function looks OK, both inlined and not, but that certainly isn't proof that gcc will always tolerate such code. I recall that there were problems handling this type of code. (never mind any non-conformant callers that actually pass a pointer to a float -- not that gcc would be able to see them in separately compiled files) So, is it fixed now? (what gcc version?) If not, is it at least fixed if I change float to void and/or unsigned char? BTW, oddly it looks like gcc tolerates a genuine aliasing violation as well now. (passing the value as a float) Of course, that may just be my luck with the optimizer. I indeed fixed the above problem at some point (4.1 may be still broken, 4.3 should be fixed I think). We're trying to tolerate genuine alias violations if we can see what the user intended (in compiler-speak, when we detect a must-alias relationship we do not try to disabiguate using type-based alias analysis). That's just being nice to users and not breaking their code just because we can. I've been trying to come up with an example where either: a. gcc gains optimization from type-based alias analysis b. traditional assumptions result in breakage I am no longer able to find either. Is it safe to consider the type-based aliasing to be essentially disabled now?
Re: old aliasing bug: fixed?
On Wed, Oct 20, 2010 at 10:29 AM, Albert Cahalan acaha...@gmail.com wrote: On Thu, Sep 30, 2010 at 5:39 AM, Richard Guenther richard.guent...@gmail.com wrote: On Thu, Sep 30, 2010 at 9:54 AM, Albert Cahalan acaha...@gmail.com wrote: int weird(float *fp){ // access an int as an int (see caller), // so not an aliasing violation return *(int*)fp; } int main(int argc, char *argv[]){ return weird((float*)argc); } I just tried this code with gcc 4.4.5 on 32-bit powerpc using -O2 -W -Wall. Assembly code for the weird function looks OK, both inlined and not, but that certainly isn't proof that gcc will always tolerate such code. I recall that there were problems handling this type of code. (never mind any non-conformant callers that actually pass a pointer to a float -- not that gcc would be able to see them in separately compiled files) So, is it fixed now? (what gcc version?) If not, is it at least fixed if I change float to void and/or unsigned char? BTW, oddly it looks like gcc tolerates a genuine aliasing violation as well now. (passing the value as a float) Of course, that may just be my luck with the optimizer. I indeed fixed the above problem at some point (4.1 may be still broken, 4.3 should be fixed I think). We're trying to tolerate genuine alias violations if we can see what the user intended (in compiler-speak, when we detect a must-alias relationship we do not try to disabiguate using type-based alias analysis). That's just being nice to users and not breaking their code just because we can. I've been trying to come up with an example where either: a. gcc gains optimization from type-based alias analysis b. traditional assumptions result in breakage I am no longer able to find either. Is it safe to consider the type-based aliasing to be essentially disabled now? int foo (int *i, float *f) { *i = 1; *f = 0; return *i; } is a case for a. We optimize this to return 1. I don't quite understand what you seek for with b, but for example for int foo (void) { int i = 1; *(float *)i = 0.0; return i; } GCC is allowed to optimize it to return 1, but for example GCC 4.6 will optimize it to return 0 as the user probably expected because when optimizing the load of i we now see a must-alias store to it. Richard.
old aliasing bug: fixed?
int weird(float *fp){ // access an int as an int (see caller), // so not an aliasing violation return *(int*)fp; } int main(int argc, char *argv[]){ return weird((float*)argc); } I just tried this code with gcc 4.4.5 on 32-bit powerpc using -O2 -W -Wall. Assembly code for the weird function looks OK, both inlined and not, but that certainly isn't proof that gcc will always tolerate such code. I recall that there were problems handling this type of code. (never mind any non-conformant callers that actually pass a pointer to a float -- not that gcc would be able to see them in separately compiled files) So, is it fixed now? (what gcc version?) If not, is it at least fixed if I change float to void and/or unsigned char? BTW, oddly it looks like gcc tolerates a genuine aliasing violation as well now. (passing the value as a float) Of course, that may just be my luck with the optimizer.
Re: old aliasing bug: fixed?
On Thu, Sep 30, 2010 at 9:54 AM, Albert Cahalan acaha...@gmail.com wrote: int weird(float *fp){ // access an int as an int (see caller), // so not an aliasing violation return *(int*)fp; } int main(int argc, char *argv[]){ return weird((float*)argc); } I just tried this code with gcc 4.4.5 on 32-bit powerpc using -O2 -W -Wall. Assembly code for the weird function looks OK, both inlined and not, but that certainly isn't proof that gcc will always tolerate such code. I recall that there were problems handling this type of code. (never mind any non-conformant callers that actually pass a pointer to a float -- not that gcc would be able to see them in separately compiled files) So, is it fixed now? (what gcc version?) If not, is it at least fixed if I change float to void and/or unsigned char? BTW, oddly it looks like gcc tolerates a genuine aliasing violation as well now. (passing the value as a float) Of course, that may just be my luck with the optimizer. I indeed fixed the above problem at some point (4.1 may be still broken, 4.3 should be fixed I think). We're trying to tolerate genuine alias violations if we can see what the user intended (in compiler-speak, when we detect a must-alias relationship we do not try to disabiguate using type-based alias analysis). That's just being nice to users and not breaking their code just because we can. Richard.
[Bug rtl-optimization/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #26 from jamborm at gcc dot gnu dot org 2010-06-07 16:51 --- *** Bug 44406 has been marked as a duplicate of this bug. *** -- jamborm at gcc dot gnu dot org changed: What|Removed |Added CC||torbenh at users dot ||sourceforge dot net http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug rtl-optimization/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #23 from rguenth at gcc dot gnu dot org 2010-05-26 10:30 --- Subject: Bug 44164 Author: rguenth Date: Wed May 26 10:30:31 2010 New Revision: 159861 URL: http://gcc.gnu.org/viewcvs?root=gccview=revrev=159861 Log: 2010-05-26 Richard Guenther rguent...@suse.de PR rtl-optimization/44164 * tree-ssa-alias.c (aliasing_component_refs_p): Fix the no-common access-path disambiguation. (indirect_ref_may_alias_decl_p): Adjust. (indirect_refs_may_alias_p): Likewise. (refs_may_alias_p_1): Likewise. * gcc.c-torture/execute/pr44164.c: New testcase. * g++.dg/tree-ssa/pr13146.C: Adjust. Added: trunk/gcc/testsuite/gcc.c-torture/execute/pr44164.c Modified: trunk/gcc/ChangeLog trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/g++.dg/tree-ssa/pr13146.C trunk/gcc/tree-ssa-alias.c -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug rtl-optimization/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #24 from rguenth at gcc dot gnu dot org 2010-05-26 11:46 --- Subject: Bug 44164 Author: rguenth Date: Wed May 26 11:46:01 2010 New Revision: 159866 URL: http://gcc.gnu.org/viewcvs?root=gccview=revrev=159866 Log: 2010-05-26 Richard Guenther rguent...@suse.de PR rtl-optimization/44164 * tree-ssa-alias.c (aliasing_component_refs_p): Fix the no-common access-path disambiguation. (indirect_ref_may_alias_decl_p): Adjust. (indirect_refs_may_alias_p): Likewise. (refs_may_alias_p_1): Likewise. * gcc.c-torture/execute/pr44164.c: New testcase. * g++.dg/tree-ssa/pr13146.C: Adjust. Added: branches/gcc-4_5-branch/gcc/testsuite/gcc.c-torture/execute/pr44164.c Modified: branches/gcc-4_5-branch/gcc/ChangeLog branches/gcc-4_5-branch/gcc/testsuite/ChangeLog branches/gcc-4_5-branch/gcc/testsuite/g++.dg/tree-ssa/pr13146.C branches/gcc-4_5-branch/gcc/tree-ssa-alias.c -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug rtl-optimization/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #25 from rguenth at gcc dot gnu dot org 2010-05-26 11:46 --- Fixed. -- rguenth at gcc dot gnu dot org changed: What|Removed |Added Status|ASSIGNED|RESOLVED Known to work|4.4.3 4.6.0 |4.4.3 4.5.1 4.6.0 Resolution||FIXED http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug rtl-optimization/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #20 from rguenth at gcc dot gnu dot org 2010-05-25 13:56 --- -fsched2-use-superblocks also fixes it. -fdbg-cnt=sched_region:65 is broken, -fdbg-cnt=sched_region:64 works for a simplified testcase tail: int bmi_get(const int* id) { if (*id != 42) __builtin_abort(); return 0; } int main() { int id = 42; typedef boost::functionint () func_t; func_t f = boost::bind(bmi_get, id); func_t g = f; g(); return 0; } Assembler difference: --- /tmp/gtest.s.ok 2010-05-25 15:51:19.0 +0200 +++ /tmp/gtest.s.broken 2010-05-25 15:51:30.0 +0200 @@ -825,21 +825,21 @@ call_ZN5boost6detail8function16has_empty_targetEz testb %al, %al jne .L93 + movq112(%rsp), %rdx leaq96(%rsp), %rbx - movq$_Z7bmi_getPKi, 104(%rsp) - movq%rbp, 16(%rbx) movl $_ZZN5boost9function0IiE9assign_toINS_3_bi6bind_tIiPFiPKiENS3_5l ist1INS3_5valueIPivT_E13stored_vtable, %eax orq $1, %rax - movq%rax, 96(%rsp) - movq%rax, 64(%rsp) + movq$_Z7bmi_getPKi, 104(%rsp) movq$_Z7bmi_getPKi, 72(%rsp) - movq112(%rsp), %rdx + movq%rbp, 16(%rbx) + leaq64(%rsp), %rbp + movq%rax, 96(%rsp) movq%rdx, 80(%rsp) movq120(%rsp), %rdx - movq%rdx, 88(%rsp) + movq%rax, 64(%rsp) andq$-2, %rax - leaq64(%rsp), %rbp leaq8(%rbp), %rdi + movq%rdx, 88(%rsp) .LEHB15: call*8(%rax) .LEHE15: Still can't see where that is broken ... :/ -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug rtl-optimization/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #21 from rguenth at gcc dot gnu dot org 2010-05-25 14:57 --- We're exchanging movq112(%rsp), %rdx and leaq96(%rsp), %rbx movq%rbp, 16(%rbx) which is broken. (insn 565 18 20 3 /usr/include/boost/function/function_template.hpp:566 (set (reg/f:DI 3 bx [242]) (plus:DI (reg/f:DI 7 sp) (const_int 96 [0x60]))) 248 {*lea_1} (nil)) (insn 23 21 24 3 gtest.cc:21 (set (mem/s/f:DI (plus:DI (reg/f:DI 3 bx [242]) (const_int 16 [0x10])) [20 D.60304_20-l_.D.57654.a1_.t_+0 S8 A64]) (reg/f:DI 6 bp [140])) 89 {*movdi_1_rex64} (expr_list:REG_DEAD (reg/f:DI 6 bp [140]) (nil))) (insn 39 38 40 3 /usr/include/boost/function/function_template.hpp:886 (set (reg:DI 1 dx [orig:146 f.D.56107.D.55977.functor+8 ] [146]) (mem/s/c:DI (plus:DI (reg/f:DI 7 sp) (const_int 112 [0x70])) [9 f.D.56107.D.55977.functor+8 S8 A64])) 89 {*movdi_1_rex64} (expr_list:REG_EQUIV (mem/s/c:DI (plus:DI (reg/f:DI 7 sp) (const_int 112 [0x70])) [9 f.D.56107.D.55977.functor+8 S8 A64]) (nil))) Relevant MEM_ATTRs are [20 D.60304_20-l_.D.57654.a1_.t_+0 S8 A64] [9 f.D.56107.D.55977.functor+8 S8 A64] struct bind_t * D.60304; struct bind_t f; struct func_t f; D.60304_20 = (struct bind_t *) f.D.56107.D.55977.functor.data; D.60304_20-l_.D.57654.a1_.t_ = id; ... g.D.56107.D.55977.functor = f.D.56107.D.55977.functor; which we disambiguate via the TBAA tree oracle as the pointed-to type by D.60304_20 is bind_t and has alias-set 21 which is not a subset of alias-set 5, the alias-set of f. This particular disambiguation would be fixed by backporting the alias_set_subset_of change. Then we disambiguate via access-path based disambiguation. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug rtl-optimization/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #22 from rguenth at gcc dot gnu dot org 2010-05-25 15:28 --- I have some patches. -- rguenth at gcc dot gnu dot org changed: What|Removed |Added AssignedTo|unassigned at gcc dot gnu |rguenth at gcc dot gnu dot |dot org |org Status|NEW |ASSIGNED Last reconfirmed|2010-05-19 22:15:45 |2010-05-25 15:28:49 date|| http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug c++/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #16 from rguenther at suse dot de 2010-05-20 11:48 --- Subject: Re: [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function On Thu, 20 May 2010, jason at gcc dot gnu dot org wrote: --- Comment #15 from jason at gcc dot gnu dot org 2010-05-20 05:35 --- Giving all unions alias set 0 doesn't fix the testcase. This surprises me, since I thought that the problem was with the union assignment this-functor = f.functor; in assign_to_own. Giving alias set 0 to all classes with a member or base of alias set 0 also doesn't fix the testcase. Giving alias set 0 to all classes does fix the testcase. Ok, I'll try to pin-point the exact problem. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug c++/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #17 from rguenth at gcc dot gnu dot org 2010-05-20 13:24 --- It is actually the scheduler that breaks the testcase. Easier to look at is -O2 -fwhole-program. -fno-schedule-insns2 fixes it (as well as -fno-tree-pre or -fno-tree-dominator-opts, both of which are necessary to produce the input to the scheduler). -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug c++/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #18 from jason at gcc dot gnu dot org 2010-05-20 14:00 --- Unassigning myself. -- jason at gcc dot gnu dot org changed: What|Removed |Added AssignedTo|jason at gcc dot gnu dot org|unassigned at gcc dot gnu ||dot org Status|ASSIGNED|NEW http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug rtl-optimization/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #19 from jason at gcc dot gnu dot org 2010-05-20 14:01 --- And changing component to rtl-opt. -- jason at gcc dot gnu dot org changed: What|Removed |Added Component|c++ |rtl-optimization http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug c++/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
-- rguenth at gcc dot gnu dot org changed: What|Removed |Added Priority|P3 |P2 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug c++/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
-- jason at gcc dot gnu dot org changed: What|Removed |Added AssignedTo|unassigned at gcc dot gnu |jason at gcc dot gnu dot org |dot org | Status|NEW |ASSIGNED Last reconfirmed|2010-05-17 15:50:41 |2010-05-19 22:15:45 date|| http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug c++/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #14 from jason at gcc dot gnu dot org 2010-05-19 22:53 --- In C++, an assignment of a union is defined to be equivalent to a byte copy: 12.8/32 The implicitly-defined copy assignment operator for a union X copies the object representation (3.9) of X. 3.9/4 The object representation of an object of type T is the sequence of N unsigned char objects taken up by the object of type T, where N equals sizeof(T). -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug c++/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #15 from jason at gcc dot gnu dot org 2010-05-20 05:35 --- Giving all unions alias set 0 doesn't fix the testcase. This surprises me, since I thought that the problem was with the union assignment this-functor = f.functor; in assign_to_own. Giving alias set 0 to all classes with a member or base of alias set 0 also doesn't fix the testcase. Giving alias set 0 to all classes does fix the testcase. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug middle-end/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #10 from rguenth at gcc dot gnu dot org 2010-05-18 14:58 --- (In reply to comment #9) But the standard says in [basic.types] that For any trivially copyable type T, if two pointers to T point to distinct T objects obj1 and obj2, where neither obj1 nor obj2 is a base-class subobject, if the underlying bytes (1.7) making up obj1 are copied into obj2,40 obj2 shall subsequently hold the same value as obj1. Yep. But an assignment is not a byte-copy and exactly the assignment is what invokes the undefined behavior (not the subsequent access). So, struct X { char data[ sizeof( float ) ]; }; int main() { X x1; new( x1.data ) float( 3.14f ); X x2 = x1; GCC sees this as reading the float object you made live in x1.data via an lvalue of type X and thus decides that the float object is unused and removes it. -- rguenth at gcc dot gnu dot org changed: What|Removed |Added CC||rguenth at gcc dot gnu dot ||org http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug middle-end/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #11 from rguenth at gcc dot gnu dot org 2010-05-18 15:00 --- (In reply to comment #10) (In reply to comment #9) But the standard says in [basic.types] that For any trivially copyable type T, if two pointers to T point to distinct T objects obj1 and obj2, where neither obj1 nor obj2 is a base-class subobject, if the underlying bytes (1.7) making up obj1 are copied into obj2,40 obj2 shall subsequently hold the same value as obj1. Yep. But an assignment is not a byte-copy and exactly the assignment is what invokes the undefined behavior (not the subsequent access). So, struct X { char data[ sizeof( float ) ]; }; int main() { X x1; new( x1.data ) float( 3.14f ); X x2 = x1; GCC sees this as reading the float object you made live in x1.data via an lvalue of type X and thus decides that the float object is unused and removes it. Oh, and float is a trivially copyable type. Copying X results in copying the bytes of X::data (because the default copy constructor of a class does a memberwise copy, and the default copy constructor of an array does an elementwise copy). Therefore, the underlying bytes of the object of type float, initialized at x1.data, are copied into x2.data, which then must, if interpreted as a float, hold the same value as the original object. is not what the C++ frontend does. It emits the assignment literally: cleanup_point Unknown tree: expr_stmt (void) (x2 = TARGET_EXPR D.21180, x1) ; gimplified to x2 = x1; -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug c++/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #12 from rguenth at gcc dot gnu dot org 2010-05-18 15:02 --- Making this a C++ frontend bug. The only way to avoid expanding the copy to a loop is by using memcpy which will then run into PR42834. -- rguenth at gcc dot gnu dot org changed: What|Removed |Added CC||jason at gcc dot gnu dot org Component|middle-end |c++ http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug c++/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #13 from pluto at agmk dot net 2010-05-18 20:57 --- btw. the boost::optional uses char-based storage and cast storage - void* - some_type* via address() and get_object() methods. it looks like aliasing violation too. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug middle-end/44164] New: [4.5.0] Aliasing bug triggered by Boost.Bind/Boost.Function
Using Boost.Bind/Boost.Function triggers what seems to be an aliasing bug with G++ 4.5.0. The minimal test case (including Boost.Bind and Boost.Function) is attached. It works and no errors are detected by valgrind with either flags : -O0 -O1 -O2 -fno-inline -O2 -fno-strict-aliasing -Os It crashes whith either flags and valgrind detects invalid reads : -02 -O3 Everything works fine with gcc version 4.4.3 20100316. There are no warnings using '-W -Wall -Wextra'. Original bug report to boost mailing list : http://lists.boost.org/boost-users/2010/05/59020.php -- Summary: [4.5.0] Aliasing bug triggered by Boost.Bind/Boost.Function Product: gcc Version: 4.5.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: maxime at altribe dot org GCC build triplet: ../configure --prefix=/usr --enable- languages=c,c++,fortran,objc GCC host triplet: x86_64-unknown-linux-gnu GCC target triplet: x86_64-unknown-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug middle-end/44164] [4.5.0] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #1 from maxime at altribe dot org 2010-05-17 08:31 --- Created an attachment (id=20677) -- (http://gcc.gnu.org/bugzilla/attachment.cgi?id=20677action=view) Test case including Boost.Bind and Boost.Function. I had to gzip the .ii file because of size limit. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug middle-end/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #2 from rguenth at gcc dot gnu dot org 2010-05-17 09:39 --- It's not a dup of PR42834 (but it might be the same issue as PR42832 which was a libstdc++ bug or a frontend bug). It happens to work on trunk, so it might also be a dup of PR43987 (though unlikely), rather different inlining might have made the bug latent. I can confirm the observed effect. I didn't investigate on whether this is a bug in boost or not (we're changing our minds on what is valid and what not all the time anyway). -- rguenth at gcc dot gnu dot org changed: What|Removed |Added Status|UNCONFIRMED |NEW Ever Confirmed|0 |1 Known to fail||4.5.0 Known to work||4.4.3 4.6.0 Last reconfirmed|-00-00 00:00:00 |2010-05-17 09:39:31 date|| Summary|[4.5.0] Aliasing bug|[4.5 Regression] Aliasing |triggered by|bug triggered by |Boost.Bind/Boost.Function |Boost.Bind/Boost.Function Target Milestone|--- |4.5.1 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug middle-end/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #3 from rguenth at gcc dot gnu dot org 2010-05-17 09:44 --- The boost folks may be able to tell if they at any place copy a function_buffer object via the assignment operator. I see they also have funny stuff like get_vtable() and are playing with typeinfos. -- rguenth at gcc dot gnu dot org changed: What|Removed |Added Status|NEW |WAITING http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug middle-end/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #4 from maxime at altribe dot org 2010-05-17 13:10 --- (In reply to comment #3) The boost folks may be able to tell if they at any place copy a function_buffer object via the assignment operator. It seems so. From Peter Dimov : [...] after stepping through the code, it turns out that function_buffer is indeed assigned directly, due to the fact that __has_trivial_copy and __has_trivial_destructor report true for the stored function object. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug middle-end/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #5 from rguenth at gcc dot gnu dot org 2010-05-17 15:50 --- (In reply to comment #4) (In reply to comment #3) The boost folks may be able to tell if they at any place copy a function_buffer object via the assignment operator. It seems so. From Peter Dimov : [...] after stepping through the code, it turns out that function_buffer is indeed assigned directly, due to the fact that __has_trivial_copy and __has_trivial_destructor report true for the stored function object. Which means that it is either a C++ frontend bug not protecting this aggregate assignment properly or a bug in Boost as the functor type stored to function_buffer is not a member of the union. The functor types are for example seen in const functor_type* in_functor = reinterpret_castconst functor_type*(in_buffer.data); new ((void*)out_buffer.data) functor_type(*in_functor); but functor_type (a template param) is not a member of said union. People were arguing that the char member in the union should make this valid, but nothing in the C++ frontend communicates that to the alias analysis stage. People also were arguing only a character array member would qualify, possibly covering the whole union in size. A workaround for boost can be constructed following the fix for PR42832. Due to an unrelated bug using memcpy for the assingment won't work. -- rguenth at gcc dot gnu dot org changed: What|Removed |Added Status|WAITING |NEW Last reconfirmed|2010-05-17 09:39:31 |2010-05-17 15:50:41 date|| http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug middle-end/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #6 from rguenth at gcc dot gnu dot org 2010-05-17 15:57 --- Basically the middle-end sees this the same as int i = 1, j; float *p = new (i) float(0.0); j = i; return *reinterpret_castfloat *(j); and you expect to return 0.0. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug middle-end/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #7 from pdimov at gmail dot com 2010-05-17 19:10 --- (In reply to comment #6) Basically the middle-end sees this the same as int i = 1, j; float *p = new (i) float(0.0); j = i; return *reinterpret_castfloat *(j); and you expect to return 0.0. The int/float example does violate the aliasing rules, but I don't think that it properly describes what's happening. I see it more like a combination of the following two examples: #include iostream struct X { char data[ sizeof( float ) ]; }; int main() { X x1; new( x1.data ) float( 3.14f ); X x2 = x1; std::cout *(float const*)x2.data std::endl; } and #include iostream union Y { int i; float f; }; int main() { Y y1; y1.f = 3.14f; Y y2 = y1; std::cout y2.f std::endl; } I don't think either of them violates the standard. -- pdimov at gmail dot com changed: What|Removed |Added CC||pdimov at gmail dot com http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug middle-end/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #8 from pinskia at gcc dot gnu dot org 2010-05-17 19:17 --- The first example I think does as there is no way to transfer the dynamic type via the struct copy. The second one does not as the union still has a field that is float and it is only unspecified behavior if you access the other field in the union (IIRC). -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
[Bug middle-end/44164] [4.5 Regression] Aliasing bug triggered by Boost.Bind/Boost.Function
--- Comment #9 from pdimov at gmail dot com 2010-05-17 20:12 --- But the standard says in [basic.types] that For any trivially copyable type T, if two pointers to T point to distinct T objects obj1 and obj2, where neither obj1 nor obj2 is a base-class subobject, if the underlying bytes (1.7) making up obj1 are copied into obj2,40 obj2 shall subsequently hold the same value as obj1. float is a trivially copyable type. Copying X results in copying the bytes of X::data (because the default copy constructor of a class does a memberwise copy, and the default copy constructor of an array does an elementwise copy). Therefore, the underlying bytes of the object of type float, initialized at x1.data, are copied into x2.data, which then must, if interpreted as a float, hold the same value as the original object. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44164
Aliasing bug
Hi all, I'm fairly sure I have found an aliasing bug in GCC, although I could be wrong. I've reproduced it in both 4.4 and mainline. Consider this testcase, aliasing.c: extern void *foo; extern inline short ** f1 (void) { union { void **v; short **s; } u; u.v = (foo); if (*u.s == 0) *u.s = (short *)42; return u.s; } const short *a, *b; int f () { a = *f1(); b = *f1(); } The (not very useful) testcase initialises foo to 42, if necessary, and then sets both 'a' and 'b' to equal foo. There should be no way that 'a' and 'b' can ever be set to zero. Compile the code as follows: sh-linux-gnu-gcc -c aliasing.c -O2 -fdump-tree-all The dump file aliasing.c.133t.optimized (the last tree dump) then contains: f () { void * foo.3; short int * D.1982; short int * * D.1973; bb 2: foo.3_10 = foo; D.1982_26 = (short int *) foo.3_10; if (D.1982_26 == 0B) goto bb 3; else goto bb 5; bb 3: D.1973_13 = (short int * *) foo; *D.1973_13 = 42B; a = 0B; bb 4: b = D.1982_26; return; bb 5: a = D.1982_26; goto bb 4; } This is the state of the code after the tree optimisations. Both 'a' and 'b' are set to the initial value of foo, before it was initialised. Not only that, but 'a' is explicitly set to zero. This problem goes away if -fno-strict-aliasing is used. Is this a compiler bug? Or have I got something wrong in my code? Thanks Andrew
Re: Aliasing bug
On Thu, Jul 2, 2009 at 3:21 PM, Andrew Stubbsa...@codesourcery.com wrote: Hi all, I'm fairly sure I have found an aliasing bug in GCC, although I could be wrong. I've reproduced it in both 4.4 and mainline. Consider this testcase, aliasing.c: extern void *foo; extern inline short ** f1 (void) { union { void **v; short **s; } u; u.v = (foo); if (*u.s == 0) *u.s = (short *)42; return u.s; } const short *a, *b; int f () { a = *f1(); b = *f1(); } The (not very useful) testcase initialises foo to 42, if necessary, and then sets both 'a' and 'b' to equal foo. There should be no way that 'a' and 'b' can ever be set to zero. Compile the code as follows: sh-linux-gnu-gcc -c aliasing.c -O2 -fdump-tree-all The dump file aliasing.c.133t.optimized (the last tree dump) then contains: f () { void * foo.3; short int * D.1982; short int * * D.1973; bb 2: foo.3_10 = foo; D.1982_26 = (short int *) foo.3_10; if (D.1982_26 == 0B) goto bb 3; else goto bb 5; bb 3: D.1973_13 = (short int * *) foo; *D.1973_13 = 42B; a = 0B; bb 4: b = D.1982_26; return; bb 5: a = D.1982_26; goto bb 4; } This is the state of the code after the tree optimisations. Both 'a' and 'b' are set to the initial value of foo, before it was initialised. Not only that, but 'a' is explicitly set to zero. This problem goes away if -fno-strict-aliasing is used. Is this a compiler bug? Or have I got something wrong in my code? You are writing to memory of type void * via an lvalue of type short *. Richard. Thanks Andrew
Re: Aliasing bug
On 02/07/09 14:26, Richard Guenther wrote: You are writing to memory of type void * via an lvalue of type short *. Yes, there is type punning there, but that should work, shouldn't it? This code is distilled from some glibc code I'm having trouble with. Andrew
Re: Aliasing bug
On Thu, Jul 2, 2009 at 3:29 PM, Andrew Stubbsa...@codesourcery.com wrote: On 02/07/09 14:26, Richard Guenther wrote: You are writing to memory of type void * via an lvalue of type short *. Yes, there is type punning there, but that should work, shouldn't it? No, that's invalid. You would have to do extern union { void *foo; short *bar; }; using the union for the double-indirect pointer doesn't help. Or simply use memcpy to store to foo. Richard.
Re: Aliasing bug
On 02/07/09 14:34, Richard Guenther wrote: No, that's invalid. You would have to do extern union { void *foo; short *bar; }; using the union for the double-indirect pointer doesn't help. Or simply use memcpy to store to foo. Ah, I did not know that. I still don't understand how a reference to a memory location that happens to contain a pointer is different to one what contains other data? Anyway, I see that the glibc code has, in fact, already been fixed here: http://sourceware.org/ml/libc-alpha/2008-11/msg4.html Thank you. Andrew
Re: Aliasing bug
Andrew Stubbs wrote: On 02/07/09 14:34, Richard Guenther wrote: No, that's invalid. You would have to do extern union { void *foo; short *bar; }; using the union for the double-indirect pointer doesn't help. Or simply use memcpy to store to foo. Ah, I did not know that. I still don't understand how a reference to a memory location that happens to contain a pointer is different to one what contains other data? It's easy enough to find out: just look at the C standard. 6.3.2.3, Pointers. Andrew.
Re: Aliasing bug
On Thu, Jul 2, 2009 at 3:46 PM, Andrew Stubbsa...@codesourcery.com wrote: On 02/07/09 14:34, Richard Guenther wrote: No, that's invalid. You would have to do extern union { void *foo; short *bar; }; using the union for the double-indirect pointer doesn't help. Or simply use memcpy to store to foo. Ah, I did not know that. I still don't understand how a reference to a memory location that happens to contain a pointer is different to one what contains other data? It is not different. Anyway, I see that the glibc code has, in fact, already been fixed here: http://sourceware.org/ml/libc-alpha/2008-11/msg4.html Great. Richard. Thank you. Andrew
[Bug tree-optimization/36493] [4.3/4.4 Regression] vectorizer aliasing bug
-- pinskia at gcc dot gnu dot org changed: What|Removed |Added CC||pinskia at gcc dot gnu dot ||org Target Milestone|--- |4.3.2 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36493
[Bug tree-optimization/36493] [4.3/4.4 Regression] vectorizer aliasing bug
--- Comment #5 from irar at il dot ibm dot com 2008-06-17 11:49 --- Fixed. -- irar at il dot ibm dot com changed: What|Removed |Added Status|NEW |RESOLVED Priority|P1 |P3 Resolution||FIXED Target Milestone|4.3.2 |--- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36493
[Bug tree-optimization/36493] [4.3/4.4 Regression] vectorizer aliasing bug
--- Comment #3 from irar at gcc dot gnu dot org 2008-06-16 10:39 --- Subject: Bug 36493 Author: irar Date: Mon Jun 16 10:39:07 2008 New Revision: 136843 URL: http://gcc.gnu.org/viewcvs?root=gccview=revrev=136843 Log: PR tree-optimization/36493 * tree-vect-transform.c (vect_create_data_ref_ptr): Remove TYPE from the arguments list. Use VECTYPE to create vector pointer. (vectorizable_store): Fail if accesses through a pointer to vectype do not alias the original memory reference operands. Call vect_create_data_ref_ptr without the removed argument. (vectorizable_load): Likewise. (vect_setup_realignment): Call vect_create_data_ref_ptr without the removed argument. Added: trunk/gcc/testsuite/gcc.dg/vect/pr36493.c Modified: trunk/gcc/ChangeLog trunk/gcc/testsuite/ChangeLog trunk/gcc/tree-vect-transform.c -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36493
[Bug tree-optimization/36493] [4.3/4.4 Regression] vectorizer aliasing bug
--- Comment #4 from irar at gcc dot gnu dot org 2008-06-16 10:43 --- Subject: Bug 36493 Author: irar Date: Mon Jun 16 10:42:56 2008 New Revision: 136844 URL: http://gcc.gnu.org/viewcvs?root=gccview=revrev=136844 Log: PR tree-optimization/36493 * tree-vect-transform.c (vect_create_data_ref_ptr): Remove TYPE from the arguments list. Use VECTYPE to create vector pointer. (vectorizable_store): Fail if accesses through a pointer to vectype do not alias the original memory reference operands. Call vect_create_data_ref_ptr without the removed argument. (vectorizable_load): Likewise. (vect_setup_realignment): Call vect_create_data_ref_ptr without the removed argument. Added: branches/gcc-4_3-branch/gcc/testsuite/gcc.dg/vect/pr36493.c Modified: branches/gcc-4_3-branch/gcc/ChangeLog branches/gcc-4_3-branch/gcc/testsuite/ChangeLog branches/gcc-4_3-branch/gcc/tree-vect-transform.c -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36493
[Bug tree-optimization/36493] [4.3/4.4 Regression] vectorizer aliasing bug
-- mmitchel at gcc dot gnu dot org changed: What|Removed |Added Priority|P3 |P1 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36493
[Bug tree-optimization/36493] [4.3/4.4 Regression] vectorizer aliasing bug
--- Comment #1 from irar at il dot ibm dot com 2008-06-11 08:00 --- Reproduced on powerpc64-suse-linux. Doesn't occur when compiled with -O2 -ftree-vectorize instead of -O3 (the vectorizer generates the same code in both cases). -- irar at il dot ibm dot com changed: What|Removed |Added Status|UNCONFIRMED |NEW Ever Confirmed|0 |1 Last reconfirmed|-00-00 00:00:00 |2008-06-11 08:00:41 date|| http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36493
[Bug tree-optimization/36493] [4.3/4.4 Regression] vectorizer aliasing bug
--- Comment #2 from rguenth at gcc dot gnu dot org 2008-06-11 08:37 --- Vectors have the alias set of their element type and int and long do not have conflicting alias sets. The vectorizer clearly should choose vector long * instead of vector int *. -- rguenth at gcc dot gnu dot org changed: What|Removed |Added CC||rguenth at gcc dot gnu dot ||org http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36493
[Bug tree-optimization/36493] [4.3/4.4 Regression] vectorizer aliasing bug
-- jsm28 at gcc dot gnu dot org changed: What|Removed |Added Target Milestone|--- |4.3.2 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36493
[Bug tree-optimization/36493] New: [4.3/4.4 Regression] vectorizer aliasing bug
The following code aborts if built for i686-pc-linux-gnu with -msse2 -O3. extern void abort (void); int main (void) { int i; long x[12] __attribute__((aligned(16))); x[0] = 1; for (i = 0; i 12; i++) x[i] = i; if (x[0] != 0) abort (); return 0; } The loop gets vectorized using vector int * pointers, and then the compiler decides that vector int writes don't conflict with long reads. (If an array of int is used instead, the test passes.) (Not x86-specific; originally observed as a failure of gcc.c-torture/execute/loop-13.c on SPE with an unsubmitted patch to support autovectorization there.) -- Summary: [4.3/4.4 Regression] vectorizer aliasing bug Product: gcc Version: 4.4.0 Status: UNCONFIRMED Keywords: wrong-code Severity: normal Priority: P3 Component: tree-optimization AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: jsm28 at gcc dot gnu dot org http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36493
[Bug fortran/34686] Aliasing bug when returning character pointers
--- Comment #3 from burnus at gcc dot gnu dot org 2008-01-18 00:29 --- Subject: Bug 34686 Author: burnus Date: Fri Jan 18 00:28:28 2008 New Revision: 131620 URL: http://gcc.gnu.org/viewcvs?root=gccview=revrev=131620 Log: 2008-01-18 Richard Sandiford [EMAIL PROTECTED] PR fortran/34686 * trans-expr.c (gfc_conv_function_call): Use proper type for returned character pointers. Modified: trunk/gcc/fortran/ChangeLog trunk/gcc/fortran/trans-expr.c -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34686
[Bug fortran/34686] Aliasing bug when returning character pointers
--- Comment #4 from burnus at gcc dot gnu dot org 2008-01-18 00:30 --- Fixed on the trunk (4.3.0). -- burnus at gcc dot gnu dot org changed: What|Removed |Added Status|ASSIGNED|RESOLVED Resolution||FIXED http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34686
[Bug fortran/34686] Aliasing bug when returning character pointers
--- Comment #2 from burnus at gcc dot gnu dot org 2008-01-14 08:58 --- Patch: http://gcc.gnu.org/ml/fortran/2008-01/msg00087.html -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34686
[Bug fortran/34686] New: Aliasing bug when returning character pointers
char_pointer_func.f90 is failing at -O3 on mips-linux-gnu because of an aliasing bug. We have a function sfoo() that returns a pointer to a string of length 4: function sfoo () result (sc1) character*4, pointer :: sc1 allocate (sc1) sc1 = abcd end function sfoo It gets the C prototype: static void sfoo (character(kind=1)[1:4] * , integer(kind=4)); However, the first caller is: c1 = sfoo () and it passes a 0-based array, pstr.3: { character(kind=1)[4] * pstr.3; sfoo (pstr.3, 4); __builtin_memmove ((void *) c1, (void *) pstr.3, 4); } So after inlining sfoo(), we get the following code at final_cleanup: D.617 = (character(kind=1)[1:4] *) D.616; *(character(kind=1)[1:4] * ) pstr.3 = D.617; __builtin_memcpy (D.617, abcd[1]{lb: 1 sz: 1}, 4); __builtin_memmove (c1, pstr.3, 4); where __builtin_memcpy is small enough to open-code; we do not use a call. The two pointer types ([4]-based and [1:4]-based) have different alias sets, so in the failing case, we then schedule the read of pstr.3 before the store to *(character(kind=1)[1:4] * ) pstr.3. The problem appears to be in this part of gfc_conv_function_call. which deliberately ignores the bounds on the return value: /* Pass the string length. */ type = gfc_get_character_type (ts.kind, ts.cl); type = build_pointer_type (type); /* Return an address to a char[0:len-1]* temporary for character pointers. */ if (sym-attr.pointer || sym-attr.allocatable) { /* Build char[0:len-1] * pstr. */ tmp = fold_build2 (MINUS_EXPR, gfc_charlen_type_node, len, build_int_cst (gfc_charlen_type_node, 1)); tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node, tmp); tmp = build_array_type (gfc_character1_type_node, tmp); var = gfc_create_var (build_pointer_type (tmp), pstr); /* Provide an address expression for the function arguments. */ var = build_fold_addr_expr (var); } else var = gfc_conv_string_tmp (se, type, len); (I believe TYPE is unused in the sym-attr.pointer || sym-attr.allocatable case). -- Summary: Aliasing bug when returning character pointers Product: gcc Version: 4.3.0 Status: UNCONFIRMED Keywords: wrong-code Severity: normal Priority: P3 Component: fortran AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: rsandifo at gcc dot gnu dot org GCC target triplet: mips-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34686
[Bug fortran/34686] Aliasing bug when returning character pointers
--- Comment #1 from rsandifo at gcc dot gnu dot org 2008-01-06 12:24 --- Testing a patch. -- rsandifo at gcc dot gnu dot org changed: What|Removed |Added AssignedTo|unassigned at gcc dot gnu |rsandifo at gcc dot gnu dot |dot org |org Status|UNCONFIRMED |ASSIGNED Ever Confirmed|0 |1 Known to fail||4.3.0 Last reconfirmed|-00-00 00:00:00 |2008-01-06 12:24:09 date|| http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34686
[Bug tree-optimization/28778] New: strict-aliasing bug
mrs $ cat /tmp/t2.cc typedef long GLint; void aglChoosePixelFormat(const GLint *); void find(const int *alistp) { const int *blist; int list[32]; if (alistp) blist = alistp; else { list[3] = 42; /* this store disappears with -fstrict-aliasing */ blist = list; } aglChoosePixelFormat((GLint*)blist); } mrs $ ./xgcc -B./ -S -O1 /tmp/t2.cc -fno-strict-aliasing grep 42 t2.s li r0,42 mrs $ ./xgcc -B./ -S -O1 /tmp/t2.cc -fstrict-aliasing grep 42 t2.s mrs $ The store cannot be removed, as the converted pointer can be used inside the aglChoosePixelFormat function to access the value. Since the optimizer can't see that it isn't used, the optimizer must assume it can as the function isn't marked pure. If it had been, then the optimization would be ok. t2.cc.035t.dce1 is the first pass that doesn't have the store, t2.cc.034t.fre has the store. This worked in 3.3, but not 4.0.1. This doesn't work in gcc version 4.2.0 20060815 (experimental) on powerpc-apple-darwin9.0.0d1, nor on i686-apple-darwin8. -- Summary: strict-aliasing bug Product: gcc Version: 4.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: mrs at apple dot com http://gcc.gnu.org/bugzilla/show_bug.cgi?id=28778
[Bug tree-optimization/28778] strict-aliasing bug
--- Comment #1 from pinskia at gcc dot gnu dot org 2006-08-18 21:11 --- As long as aglChoosePixelFormat only access the argument as int and not long, this should be ok. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=28778
[Bug tree-optimization/28778] strict-aliasing bug
--- Comment #2 from mrs at apple dot com 2006-08-18 21:12 --- radr://4658741 -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=28778
[Bug tree-optimization/28778] strict-aliasing bug
--- Comment #3 from pinskia at gcc dot gnu dot org 2006-08-18 21:15 --- Here is a full testcase: typedef long GLint; void aglChoosePixelFormat(const GLint *); void find(const int *alistp) { const int *blist; int list[32]; if (alistp) blist = alistp; else { list[3] = 42; blist = list; } aglChoosePixelFormat((GLint*)blist); } void aglChoosePixelFormat(const GLint *a) { int *b = (int*)a; if (b[3] != 42) __builtin_abort (); } int main(void) { find(0); return 0; } -- pinskia at gcc dot gnu dot org changed: What|Removed |Added Keywords||wrong-code http://gcc.gnu.org/bugzilla/show_bug.cgi?id=28778
[Bug tree-optimization/18727] [4.0 Regression] ACATS c43214c fails at runtime (tree-dce/aliasing bug)
--- Additional Comments From ebotcazou at gcc dot gnu dot org 2005-02-20 16:38 --- Investigating. -- What|Removed |Added AssignedTo|unassigned at gcc dot gnu |ebotcazou at gcc dot gnu dot |dot org |org Status|NEW |ASSIGNED http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18727