Today's trunk produces a lot of warnings / notes all referring to functions from libgfortran, when compiling CP2K with LTO. I'm looking at generating a reduced testcase, but the first obvious tries didn't work. /data/vjoost/gnu/cp2k/cp2k/makefiles/../src/dbcsr_lib/dbcsr_block_access_c.F:709:0: note: ‘_gfortran_reshape_c4’ was previously declared here data_block%p(:,:) = RESHAPE (block, (/row_size, col_size/)) /data/vjoost/gnu/cp2k/cp2k/makefiles/../src/dbcsr_lib/dbcsr_block_access_c.F:709:0: note: code may be misoptimized unless -fno-strict-aliasing is used /data/vjoost/gnu/cp2k/cp2k/makefiles/../src/helium_methods.F:1071:0: warning: type of ‘_gfortran_unpack1’ does not match original declaration [-Wlto-type-mismatch] helium%pos(:,:,:) = UNPACK(message(offset+1:offset+msglen), MASK=m, FIELD=f ) /data/vjoost/gnu/cp2k/cp2k/makefiles/../src/helium_methods.F:1699:0: warning: type of ‘_gfortran_unpack1’ does not match original declaration [-Wlto-type-mismatch] helium%rho_rstr(:,:,:,:) = UNPACK(message(1:msglen), MASK=m, FIELD=f) /data/vjoost/gnu/cp2k/cp2k/makefiles/../src/helium_methods.F:1547:0: note: ‘_gfortran_unpack1’ was previously declared here ig(:,:) = UNPACK(message(offset+33:offset+38), MASK=m, FIELD=f ) /data/vjoost/gnu/cp2k/cp2k/makefiles/../src/helium_methods.F:1547:0: note: code may be misoptimized unless -fno-strict-aliasing is used /data/vjoost/gnu/cp2k/cp2k/makefiles/../src/dbcsr_lib/dbcsr_block_access_s.F:709:0: warning: type of ‘_gfortran_reshape_r4’ does not match original declaration [-Wlto-type-mismatch] data_block%p(:,:) = RESHAPE (block, (/row_size, col_size/)) /data/vjoost/gnu/cp2k/cp2k/makefiles/../src/dbcsr_lib/dbcsr_block_access_s.F:709:0: warning: type of ‘_gfortran_reshape_r4’ does not match original declaration [-Wlto-type-mismatch]
testcase > cat foo.f90 SUBROUTINE s8(a8,b8) REAL*8 :: a8(16),b8(4,4) a8=RESHAPE(b8,(/16/)) b8=RESHAPE(a8,(/4,4/)) END SUBROUTINE REAL*8 :: a8(16),b8(4,4) CALL RANDOM_NUMBER(b8) CALL s8(a8,b8) WRITE(6,*) MAXVAL(a8),MAXVAL(b8) END > gfortran -flto -O3 foo.f90 foo.f90:3:0: warning: type of ‘_gfortran_reshape_r8’ does not match original declaration [-Wlto-type-mismatch] a8=RESHAPE(b8,(/16/)) foo.f90:4:0: note: ‘_gfortran_reshape_r8’ was previously declared here b8=RESHAPE(a8,(/4,4/)) foo.f90:4:0: note: code may be misoptimized unless -fno-strict-aliasing is used
This smells like a fortran front-end issue where _gfortran_reshape_r8's decl is created twice with two different argument types.
Grepping the list of 'note:' in our build process, it triggers for at least these functions: _gfortran_matmul_r8 _gfortran_reshape_4 _gfortran_reshape_c4 _gfortran_reshape_c8 _gfortran_reshape_r4 _gfortran_reshape_r8 _gfortran_unpack1 so it is somewhat general.
I think it is a duplicate of pr68560. > This smells like a fortran front-end issue where _gfortran_reshape_r8's decl > is created twice with two different argument types. I don't think so. I think -Wlto-type-mismatch does not know part of the Fortran syntax.
(In reply to Dominique d'Humieres from comment #4) > I think it is a duplicate of pr68560. seems certainly related, but PR68560 doesn't yield the worrying 'code may be misoptimized unless -fno-strict-aliasing is used'. I'll just add a dependency. > > > This smells like a fortran front-end issue where _gfortran_reshape_r8's decl > > is created twice with two different argument types. > > I don't think so. I think -Wlto-type-mismatch does not know part of the > Fortran syntax. I'm thinking the issue is on the Fortran FE side, LTO shouldn't know the language involved. I guess some middle end person might need to have a look however. I'm guessing it is related to the fact that _gfortran_reshape_r8 is being called with different pointer arguments (from -fdump-tree-original): struct array1_real(kind=8) parm.0; _gfortran_reshape_r8 (&parm.0, D.3433, D.3437, 0B, 0B); struct array2_real(kind=8) parm.4; _gfortran_reshape_r8 (&parm.4, D.3446, D.3450, 0B, 0B); maybe for correctness there should be some casts ?
> seems certainly related, but PR68560 doesn't yield the worrying > 'code may be misoptimized unless -fno-strict-aliasing is used'. > I'll just add a dependency. IMO these warnings are false positive (aka bogus). The minimal set of options to get the warning for the test in comment 1 is '-flto -fstrict-aliasing'. > I'm thinking the issue is on the Fortran FE side, LTO shouldn't know > the language involved. I guess some middle end person might need to have > a look however. IMO the first step is to understand why LTO is emitting these warning on valid Fortran code. Then, if this not due to a bug in LTO, it will be time to find how Fortran intrinsics have to be "decorated" to avoid the warnings.
The function is: <function_decl 0x7ffff6cc1380 _gfortran_reshape_r8 type <function_type 0x7ffff6cc3930 type <void_type 0x7ffff6af0150 void VOID align 8 symtab 0 alias set -1 structural equality pointer_to_this <pointer_type 0x7ffff6af02a0>> QI size <integer_cst 0x7ffff6ad7ca8 constant 8> unit size <integer_cst 0x7ffff6ad7cc0 constant 1> align 8 symtab 0 alias set -1 structural equality attributes <tree_list 0x7ffff6cc2140 purpose <identifier_node 0x7ffff6b09a78 fn spec> value <tree_list 0x7ffff6cc2118 value <string_cst 0x7ffff6cb72e0 constant ".wrrrr">>> arg-types <tree_list 0x7ffff6cc2258 value <reference_type 0x7ffff6cc3888> chain <tree_list 0x7ffff6cbcf28 value <reference_type 0x7ffff6cbfe70> chain <tree_list 0x7ffff6cbcf00 value <reference_type 0x7ffff6cbfd20> chain <tree_list 0x7ffff6cbced8 value <pointer_type 0x7ffff6af0738> chain <tree_list 0x7ffff6cbceb0 value <pointer_type 0x7ffff6cbaf18> chain <tree_list 0x7ffff6ae99b0>>>>>> pointer_to_this <pointer_type 0x7ffff6cc79d8>> addressable public external QI file a.f90 line 3 col 0 align 8 context <translation_unit_decl 0x7ffff6ae1168 D.3880>> Second decl is: <function_decl 0x7ffff6cc12a0 _gfortran_reshape_r8 type <function_type 0x7ffff6cc3498 type <void_type 0x7ffff6af0150 void VOID align 8 symtab 0 alias set -1 structural equality pointer_to_this <pointer_type 0x7ffff6af02a0>> QI size <integer_cst 0x7ffff6ad7ca8 constant 8> unit size <integer_cst 0x7ffff6ad7cc0 constant 1> align 8 symtab 0 alias set -1 structural equality attributes <tree_list 0x7ffff6cc2140 purpose <identifier_node 0x7ffff6b09a78 fn spec> value <tree_list 0x7ffff6cc2118 value <string_cst 0x7ffff6cb72e0 constant ".wrrrr">>> arg-types <tree_list 0x7ffff6cc20f0 value <reference_type 0x7ffff6cc33f0> chain <tree_list 0x7ffff6cbcf28 value <reference_type 0x7ffff6cbfe70> chain <tree_list 0x7ffff6cbcf00 value <reference_type 0x7ffff6cbfd20> chain <tree_list 0x7ffff6cbced8 value <pointer_type 0x7ffff6af0738> chain <tree_list 0x7ffff6cbceb0 value <pointer_type 0x7ffff6cbaf18> chain <tree_list 0x7ffff6ae99b0>>>>>> pointer_to_this <pointer_type 0x7ffff6cc7d20>> addressable public external QI file a.f90 line 4 col 0 align 8 context <translation_unit_decl 0x7ffff6ae1168 D.3880>> The reason is that the declaration is duplicated (that by itself is a bug violating one-decl rule) and we warn because reference type 0x7ffff6cc3888 is not compatible with reference type 0x7ffff6cc33f0. They point to different type of structure: <reference_type 0x7ffff6cc3888 type <record_type 0x7ffff6cc37e0 array1_real(kind=8) BLK size <integer_cst 0x7ffff6cabd08 constant 384> unit size <integer_cst 0x7ffff6cabd98 constant 48> align 64 symtab 0 alias set -1 canonical type 0x7ffff6cc3690 fields <field_decl 0x7ffff6cbebe0 data type <pointer_type 0x7ffff6cbff18> unsigned DI file a.f90 line 3 col 0 size <integer_cst 0x7ffff6ad7bb8 constant 64> unit size <integer_cst 0x7ffff6ad7bd0 constant 8> align 64 offset_align 128 offset <integer_cst 0x7ffff6ad7be8 constant 0> bit offset <integer_cst 0x7ffff6ad7c30 constant 0> context <record_type 0x7ffff6cc3690 array_descriptor1> chain <field_decl 0x7ffff6cbeb48 offset>> reference_to_this <reference_type 0x7ffff6cc3888> chain <type_decl 0x7ffff6cc4000 D.3909>> unsigned DI size <integer_cst 0x7ffff6ad7bb8 64> unit size <integer_cst 0x7ffff6ad7bd0 8> align 64 symtab 0 alias set 6 structural equality> compared to: <reference_type 0x7ffff6cc33f0 type <record_type 0x7ffff6cc3348 array2_real(kind=8) BLK size <integer_cst 0x7ffff6cabdb0 constant 576> unit size <integer_cst 0x7ffff6cabde0 constant 72> align 64 symtab 0 alias set -1 canonical type 0x7ffff6cc31f8 fields <field_decl 0x7ffff6cbe558 data type <pointer_type 0x7ffff6cbff18> unsigned DI file a.f90 line 4 col 0 size <integer_cst 0x7ffff6ad7bb8 constant 64> unit size <integer_cst 0x7ffff6ad7bd0 constant 8> align 64 offset_align 128 offset <integer_cst 0x7ffff6ad7be8 constant 0> bit offset <integer_cst 0x7ffff6ad7c30 constant 0> context <record_type 0x7ffff6cc31f8 array_descriptor2> chain <field_decl 0x7ffff6cbe4c0 offset>> reference_to_this <reference_type 0x7ffff6cc33f0> chain <type_decl 0x7ffff6cbe980 D.3898>> unsigned DI size <integer_cst 0x7ffff6ad7bb8 64> unit size <integer_cst 0x7ffff6ad7bd0 8> align 64 symtab 0 alias set 7 structural equality> Notice the difference in size of the records. This will indeed make TBAA code to believe that those two pointers are not compatible. In libgfortran there is void reshape_r8 (gfc_array_r8 * const restrict ret, gfc_array_r8 * const restrict source, shape_type * const restrict shape, gfc_array_r8 * const restrict pad, shape_type * const restrict order) ideally the fortran-fe produced declaration of reshape_r8 should be just one per unit and interoperable with the declaration above that is pointer to: #define GFC_ARRAY_DESCRIPTOR(r, type) \ struct {\ type *base_addr;\ size_t offset;\ index_type dtype;\ descriptor_dimension dim[r];\ }
Further reduced test REAL*8 :: a8(16),b8(4,4), c8(16), d8(4,4) c8=RESHAPE(b8,(/16/)) d8=RESHAPE(a8,(/4,4/)) END > Notice the difference in size of the records. How do they relate to the array sizes? From https://gcc.gnu.org/onlinedocs/gfortran/RESHAPE.html#RESHAPE Description: Reshapes SOURCE to correspond to SHAPE. If necessary, the new array may be padded with elements from PAD or permuted as defined by ORDER. > In libgfortran there is > void > reshape_r8 (gfc_array_r8 * const restrict ret, > gfc_array_r8 * const restrict source, > shape_type * const restrict shape, > gfc_array_r8 * const restrict pad, > shape_type * const restrict order) > > ideally the fortran-fe produced declaration of reshape_r8 should be just one per > unit and interoperable with the declaration above that is pointer to: > #define GFC_ARRAY_DESCRIPTOR(r, type) \ > struct {\ > type *base_addr;\ > size_t offset;\ > index_type dtype;\ > descriptor_dimension dim[r];\ > } Are you meaning that fortran-fe should produce one reshape_r8xx per shape of source?
See also pr68717 for more warnings after r231239.
This PR is tagged as a regression. Has anyone determined when it last worked or is it longstanding bug uncovered by recent non-fortran fe changes?
(In reply to Jerry DeLisle from comment #10) > This PR is tagged as a regression. Has anyone determined when it last > worked or is it longstanding bug uncovered by recent non-fortran fe changes? For users it is a regression in the sense that packages that compiled with -flto -Werror with 5.3 will now stop building. The underlying FE issue is much older, I guess.
This is of course Fortran FE bug. What is the Fortran FE emitting right now is kind like invalid C (and invalid middle-end) below. It wouldn't be invalid C++, but for C++ that would be different baz functions and name mangling would differentiate those; that is not what is going on in C or in what libgfortran expects: typedef __SIZE_TYPE__ size_t; struct D { long stride, lower_bound, ubound; }; struct A { float *base_addr; size_t offset; long dtype; struct D dim[7]; }; struct A1 { float *base_addr; size_t offset; long dtype; struct D dim[1]; }; struct A2 { float *base_addr; size_t offset; long dtype; struct D dim[2]; }; void foo (void) { extern void baz (struct A1 *); struct A1 a1 = { 0, 0, 0, { { 0, 0, 0 } } }; baz (&a1); } void bar (void) { extern void baz (struct A2 *); struct A2 a2 = { 0, 0, 0, { { 0, 0, 0 }, { 0, 0, 0 } } }; baz (&a2); } Above, A stands for generic real(8) array descriptor type that supports up to maximum number of dimensions, A1 for rank 1 and A2 for rank 2 real(8) array descriptor. IMHO you want instead: typedef __SIZE_TYPE__ size_t; struct D { long stride, lower_bound, ubound; }; struct A { float *base_addr; size_t offset; long dtype; struct D dim[7]; }; struct A1 { float *base_addr; size_t offset; long dtype; struct D dim[1]; }; struct A2 { float *base_addr; size_t offset; long dtype; struct D dim[2]; }; void foo (void) { extern void baz (struct A *); struct A1 a1 = { 0, 0, 0, { { 0, 0, 0 } } }; baz ((struct A *) &a1); } void bar (void) { extern void baz (struct A *); struct A2 a2 = { 0, 0, 0, { { 0, 0, 0 }, { 0, 0, 0 } } }; baz ((struct A *) &a2); } and ensure that A/A1/A2 etc. (the various types created by gfc_get_array_type_bounds) have the same TYPE_ALIAS to make the alias oracle happy. I hope only the libgfortran intrinsics that handle various ranks by the same function are a problem, therefore I'd say you should be marking the symbols for those intrinsics with some flag that you want to treat their arguments like assumed rank arrays, and then just cast the addresses of the descriptors you want to pass to them to some reference type to assumed rank descriptor type (dunno if just array7_real(kind=8) (i.e. maximum rank), or something else). Now, the question is if this affects just the intrinsic routines from libgfortran, or user written functions/subroutines too. I hope the latter only should be called with the right rank except for assumed
Note that the cast doesn't help in itself (but for the warning) as Jakub notices. The deeper issue is type-based aliasing here. IMHO libgfortran would need to use struct A { float *base_addr; size_t offset; long dtype; struct D dim[1]; } *desc; aka a pointer to a descriptor with flexible array member. Which I hope ends up aliasing with one with a different size. Well, we treat 'dim' as flexible array member in any case but I'm not aware of any code in alias.c that makes this work. struct Xflex { int n; int a[1]; }; struct Xspecific { int n; int a[7]; } x; int foo (struct Xflex *f) { f->a[6] = 2; x.a[6] = 1; return f->a[6]; } returns 2 with -fstrict-aliasing :( Thus even the proposed fix won't end up working.
GCC 6.1 has been released.
GCC 6.2 is being released, adjusting target milestone.
since this PR, and the related PR77278 can presumably only be fixed by changing libgfortran abi (at least if I understand Richard's suggestion for fixing this). The announced major version bump of libgfortran (https://gcc.gnu.org/ml/gcc-patches/2016-10/msg01376.html) could be a good opportunity for this change. It is the major thing holding back the use of LTO with Fortran projects, I think.
GCC 6.3 is being released, adjusting target milestone.
GCC 6.4 is being released, adjusting target milestone.
Bug 80379 is related
What we _could_ do with our array descriptors is to cast them to a pointer containing a flexible array member, i.e. struct type_descr { type *base_addr; size_t offset; dtype_type dtype; index_type span; descriptor_dimension dim[]; } which would make all our function calls equal. I have lightly tested the concept with a C program, i.e. foo.c: struct Xflex { int n; int a[]; }; int foo (struct Xflex *f) { int i; int s; s = 0; for (i=0; i<f->n; i++) s += f->a[i]; return s; } bar.c: #include <stdio.h> struct Xflex { int n; int a[]; }; struct X2 { int n; int a[2]; }; struct X2 x; int foo (struct Xflex *f); int main(void) { x.n = 2; x.a[0] = 1; x.a[1] = 3; printf("%d\n", foo((struct Xflex *) &x)); } which seems to work.
GCC 6 branch is being closed
The warnings are gone between revisions r265814 and r265942.
(In reply to Dominique d'Humieres from comment #24) > The warnings are gone between revisions r265814 and r265942. I can confirm that. So, are there objections to just committing a test case and closing this bug?
> > The warnings are gone between revisions r265814 and r265942. > > I can confirm that. > So, are there objections to just committing a test case and > closing this bug? My (shallow) understanding of the above thread was that the warning made sense. If this is still true, then the missing warning is a regression. If not, why?
See pr68717 comment 11, closing.