Message ID | 1457348563-3326-1-git-send-email-alan.lawrence@arm.com |
---|---|
State | New |
Headers | show |
On 07/03/16 11:02, Alan Lawrence wrote: > On 04/03/16 13:27, Richard Biener wrote: >> I think to make it work with LTO you need to mark it 'Optimization'. >> Also it's about >> arrays so maybe >> >> 'Assume common declarations may be overridden with ones with a larger >> trailing array' >> >> also if we document it here we should eventually document it in invoke.texi. >> >> Not sure if "unknown commons" is a good term, maybe "unconstrained >> commons" instead? > > All done; I doubt there is really a good word, unconstrained seems as good as > any. I've reused much the same wording in invoke.texi, unless you think there > is more to add. > > On 04/03/16 13:33, Jakub Jelinek wrote: >> Also, isn't the *.opt description line supposed to end with a full stop? > > Ah, yes, thanks. > > Is this version OK for trunk? > > gcc/ChangeLog: > > DATE Alan Lawrence <alan.lawrence@arm.com> > Jakub Jelinek <jakub@redhat.com> > > * common.opt (funconstrained-commons, flag_unconstrained_commons): New. > * tree.c (array_at_struct_end_p): Do not limit to size of decl for > DECL_COMMONS if flag_unconstrained_commons is set. > * tree-dfa.c (get_ref_base_and_extent): Likewise. And add to that * doc/invoke.texi (Optimize Options): Add -funconstrained-commons. (funconstrained-commons): Document. Thanks, Alan > > gcc/testsuite/ChangeLog: > > * gfortran.dg/unconstrained_commons.f: New. > --- > gcc/common.opt | 5 +++++ > gcc/doc/invoke.texi | 8 +++++++- > gcc/testsuite/gfortran.dg/unconstrained_commons.f | 20 ++++++++++++++++++++ > gcc/tree-dfa.c | 15 ++++++++++++++- > gcc/tree.c | 6 ++++-- > 5 files changed, 50 insertions(+), 4 deletions(-) > create mode 100644 gcc/testsuite/gfortran.dg/unconstrained_commons.f > > diff --git a/gcc/common.opt b/gcc/common.opt > index 520fa9c..bbf79ef 100644 > --- a/gcc/common.opt > +++ b/gcc/common.opt > @@ -2451,6 +2451,11 @@ fsplit-paths > Common Report Var(flag_split_paths) Init(0) Optimization > Split paths leading to loop backedges. > > +funconstrained-commons > +Common Var(flag_unconstrained_commons) Optimization > +Assume common declarations may be overridden with ones with a larger > +trailing array. > + > funit-at-a-time > Common Report Var(flag_unit_at_a_time) Init(1) > Compile whole compilation unit at a time. > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi > index 0a2a6f4..68933a1 100644 > --- a/gcc/doc/invoke.texi > +++ b/gcc/doc/invoke.texi > @@ -407,7 +407,7 @@ Objective-C and Objective-C++ Dialects}. > -ftree-parallelize-loops=@var{n} -ftree-pre -ftree-partial-pre -ftree-pta @gol > -ftree-reassoc -ftree-sink -ftree-slsr -ftree-sra @gol > -ftree-switch-conversion -ftree-tail-merge -ftree-ter @gol > --ftree-vectorize -ftree-vrp @gol > +-ftree-vectorize -ftree-vrp -funconstrained-commons @gol > -funit-at-a-time -funroll-all-loops -funroll-loops @gol > -funsafe-loop-optimizations -funsafe-math-optimizations -funswitch-loops @gol > -fipa-ra -fvariable-expansion-in-unroller -fvect-cost-model -fvpt @gol > @@ -6659,6 +6659,12 @@ the loop optimizer itself cannot prove that these assumptions are valid. > If you use @option{-Wunsafe-loop-optimizations}, the compiler warns you > if it finds this kind of loop. > > +@item -funconstrained-commons > +@opindex funconstrained-commons > +This option tells the compiler that variables declared in common blocks > +(e.g. Fortran) may later be overridden with longer trailing arrays. This > +prevents certain optimizations that depend on knowing the array bounds. > + > @item -fcrossjumping > @opindex fcrossjumping > Perform cross-jumping transformation. > diff --git a/gcc/testsuite/gfortran.dg/unconstrained_commons.f b/gcc/testsuite/gfortran.dg/unconstrained_commons.f > new file mode 100644 > index 0000000..f9fc471 > --- /dev/null > +++ b/gcc/testsuite/gfortran.dg/unconstrained_commons.f > @@ -0,0 +1,20 @@ > +! { dg-do compile } > +! { dg-options "-O3 -funconstrained-commons -fdump-tree-dom2-details" } > + > +! Test for PR69368: a single-element array in a common block, which will be > +! overridden with a larger size at link time (contrary to language spec). > +! Dominator opts considers accesses to differently-computed elements of X as > +! equivalent, unless -funconstrained-commons is passed in. > + SUBROUTINE FOO > + IMPLICIT DOUBLE PRECISION (X) > + INTEGER J > + COMMON /MYCOMMON / X(1) > + DO 10 J=1,1024 > + X(J+1)=X(J+7) > + 10 CONTINUE > + RETURN > + END > +! { dg-final { scan-tree-dump-not "FIND" "dom2" } } > +! We should retain both a read and write of mycommon.x. > +! { dg-final { scan-tree-dump-times " _\[0-9\]+ = mycommon\\.x\\\[_\[0-9\]+\\\];" 1 "dom2" } } > +! { dg-final { scan-tree-dump-times " mycommon\\.x\\\[_\[0-9\]+\\\] = _\[0-9\]+;" 1 "dom2" } } > diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c > index 0e98056..f133abc 100644 > --- a/gcc/tree-dfa.c > +++ b/gcc/tree-dfa.c > @@ -612,9 +612,22 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, > > if (DECL_P (exp)) > { > + if (flag_unconstrained_commons > + && TREE_CODE (exp) == VAR_DECL && DECL_COMMON (exp)) > + { > + tree sz_tree = TYPE_SIZE (TREE_TYPE (exp)); > + /* If size is unknown, or we have read to the end, assume there > + may be more to the structure than we are told. */ > + if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE > + || (seen_variable_array_ref > + && (sz_tree == NULL_TREE > + || TREE_CODE (sz_tree) != INTEGER_CST > + || (bit_offset + maxsize == wi::to_offset (sz_tree))))) > + maxsize = -1; > + } > /* If maxsize is unknown adjust it according to the size of the > base decl. */ > - if (maxsize == -1 > + else if (maxsize == -1 > && DECL_SIZE (exp) > && TREE_CODE (DECL_SIZE (exp)) == INTEGER_CST) > maxsize = wi::to_offset (DECL_SIZE (exp)) - bit_offset; > diff --git a/gcc/tree.c b/gcc/tree.c > index 07cb9d9..9179b37 100644 > --- a/gcc/tree.c > +++ b/gcc/tree.c > @@ -12957,8 +12957,10 @@ array_at_struct_end_p (tree ref) > } > > /* If the reference is based on a declared entity, the size of the array > - is constrained by its given domain. */ > - if (DECL_P (ref)) > + is constrained by its given domain. (Do not trust commons PR/69368). */ > + if (DECL_P (ref) > + && !(flag_unconstrained_commons > + && TREE_CODE (ref) == VAR_DECL && DECL_COMMON (ref))) > return false; > > return true; >
On Wed, Mar 9, 2016 at 6:54 PM, Alan Lawrence <alan.lawrence@foss.arm.com> wrote: > On 07/03/16 11:02, Alan Lawrence wrote: >> >> On 04/03/16 13:27, Richard Biener wrote: >>> >>> I think to make it work with LTO you need to mark it 'Optimization'. >>> Also it's about >>> arrays so maybe >>> >>> 'Assume common declarations may be overridden with ones with a larger >>> trailing array' >>> >>> also if we document it here we should eventually document it in >>> invoke.texi. >>> >>> Not sure if "unknown commons" is a good term, maybe "unconstrained >>> commons" instead? >> >> >> All done; I doubt there is really a good word, unconstrained seems as good >> as >> any. I've reused much the same wording in invoke.texi, unless you think >> there >> is more to add. >> >> On 04/03/16 13:33, Jakub Jelinek wrote: >>> >>> Also, isn't the *.opt description line supposed to end with a full stop? >> >> >> Ah, yes, thanks. >> >> Is this version OK for trunk? >> >> gcc/ChangeLog: >> >> DATE Alan Lawrence <alan.lawrence@arm.com> >> Jakub Jelinek <jakub@redhat.com> >> >> * common.opt (funconstrained-commons, >> flag_unconstrained_commons): New. >> * tree.c (array_at_struct_end_p): Do not limit to size of decl >> for >> DECL_COMMONS if flag_unconstrained_commons is set. >> * tree-dfa.c (get_ref_base_and_extent): Likewise. > > > And add to that > * doc/invoke.texi (Optimize Options): Add -funconstrained-commons. > (funconstrained-commons): Document. Ok. Richard. > Thanks, > Alan > >> >> gcc/testsuite/ChangeLog: >> >> * gfortran.dg/unconstrained_commons.f: New. >> --- >> gcc/common.opt | 5 +++++ >> gcc/doc/invoke.texi | 8 +++++++- >> gcc/testsuite/gfortran.dg/unconstrained_commons.f | 20 >> ++++++++++++++++++++ >> gcc/tree-dfa.c | 15 ++++++++++++++- >> gcc/tree.c | 6 ++++-- >> 5 files changed, 50 insertions(+), 4 deletions(-) >> create mode 100644 gcc/testsuite/gfortran.dg/unconstrained_commons.f >> >> diff --git a/gcc/common.opt b/gcc/common.opt >> index 520fa9c..bbf79ef 100644 >> --- a/gcc/common.opt >> +++ b/gcc/common.opt >> @@ -2451,6 +2451,11 @@ fsplit-paths >> Common Report Var(flag_split_paths) Init(0) Optimization >> Split paths leading to loop backedges. >> >> +funconstrained-commons >> +Common Var(flag_unconstrained_commons) Optimization >> +Assume common declarations may be overridden with ones with a larger >> +trailing array. >> + >> funit-at-a-time >> Common Report Var(flag_unit_at_a_time) Init(1) >> Compile whole compilation unit at a time. >> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi >> index 0a2a6f4..68933a1 100644 >> --- a/gcc/doc/invoke.texi >> +++ b/gcc/doc/invoke.texi >> @@ -407,7 +407,7 @@ Objective-C and Objective-C++ Dialects}. >> -ftree-parallelize-loops=@var{n} -ftree-pre -ftree-partial-pre >> -ftree-pta @gol >> -ftree-reassoc -ftree-sink -ftree-slsr -ftree-sra @gol >> -ftree-switch-conversion -ftree-tail-merge -ftree-ter @gol >> --ftree-vectorize -ftree-vrp @gol >> +-ftree-vectorize -ftree-vrp -funconstrained-commons @gol >> -funit-at-a-time -funroll-all-loops -funroll-loops @gol >> -funsafe-loop-optimizations -funsafe-math-optimizations -funswitch-loops >> @gol >> -fipa-ra -fvariable-expansion-in-unroller -fvect-cost-model -fvpt @gol >> @@ -6659,6 +6659,12 @@ the loop optimizer itself cannot prove that these >> assumptions are valid. >> If you use @option{-Wunsafe-loop-optimizations}, the compiler warns you >> if it finds this kind of loop. >> >> +@item -funconstrained-commons >> +@opindex funconstrained-commons >> +This option tells the compiler that variables declared in common blocks >> +(e.g. Fortran) may later be overridden with longer trailing arrays. This >> +prevents certain optimizations that depend on knowing the array bounds. >> + >> @item -fcrossjumping >> @opindex fcrossjumping >> Perform cross-jumping transformation. >> diff --git a/gcc/testsuite/gfortran.dg/unconstrained_commons.f >> b/gcc/testsuite/gfortran.dg/unconstrained_commons.f >> new file mode 100644 >> index 0000000..f9fc471 >> --- /dev/null >> +++ b/gcc/testsuite/gfortran.dg/unconstrained_commons.f >> @@ -0,0 +1,20 @@ >> +! { dg-do compile } >> +! { dg-options "-O3 -funconstrained-commons -fdump-tree-dom2-details" } >> + >> +! Test for PR69368: a single-element array in a common block, which will >> be >> +! overridden with a larger size at link time (contrary to language spec). >> +! Dominator opts considers accesses to differently-computed elements of X >> as >> +! equivalent, unless -funconstrained-commons is passed in. >> + SUBROUTINE FOO >> + IMPLICIT DOUBLE PRECISION (X) >> + INTEGER J >> + COMMON /MYCOMMON / X(1) >> + DO 10 J=1,1024 >> + X(J+1)=X(J+7) >> + 10 CONTINUE >> + RETURN >> + END >> +! { dg-final { scan-tree-dump-not "FIND" "dom2" } } >> +! We should retain both a read and write of mycommon.x. >> +! { dg-final { scan-tree-dump-times " _\[0-9\]+ = >> mycommon\\.x\\\[_\[0-9\]+\\\];" 1 "dom2" } } >> +! { dg-final { scan-tree-dump-times " mycommon\\.x\\\[_\[0-9\]+\\\] = >> _\[0-9\]+;" 1 "dom2" } } >> diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c >> index 0e98056..f133abc 100644 >> --- a/gcc/tree-dfa.c >> +++ b/gcc/tree-dfa.c >> @@ -612,9 +612,22 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT >> *poffset, >> >> if (DECL_P (exp)) >> { >> + if (flag_unconstrained_commons >> + && TREE_CODE (exp) == VAR_DECL && DECL_COMMON (exp)) >> + { >> + tree sz_tree = TYPE_SIZE (TREE_TYPE (exp)); >> + /* If size is unknown, or we have read to the end, assume there >> + may be more to the structure than we are told. */ >> + if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE >> + || (seen_variable_array_ref >> + && (sz_tree == NULL_TREE >> + || TREE_CODE (sz_tree) != INTEGER_CST >> + || (bit_offset + maxsize == wi::to_offset >> (sz_tree))))) >> + maxsize = -1; >> + } >> /* If maxsize is unknown adjust it according to the size of the >> base decl. */ >> - if (maxsize == -1 >> + else if (maxsize == -1 >> && DECL_SIZE (exp) >> && TREE_CODE (DECL_SIZE (exp)) == INTEGER_CST) >> maxsize = wi::to_offset (DECL_SIZE (exp)) - bit_offset; >> diff --git a/gcc/tree.c b/gcc/tree.c >> index 07cb9d9..9179b37 100644 >> --- a/gcc/tree.c >> +++ b/gcc/tree.c >> @@ -12957,8 +12957,10 @@ array_at_struct_end_p (tree ref) >> } >> >> /* If the reference is based on a declared entity, the size of the >> array >> - is constrained by its given domain. */ >> - if (DECL_P (ref)) >> + is constrained by its given domain. (Do not trust commons >> PR/69368). */ >> + if (DECL_P (ref) >> + && !(flag_unconstrained_commons >> + && TREE_CODE (ref) == VAR_DECL && DECL_COMMON (ref))) >> return false; >> >> return true; >> >
diff --git a/gcc/common.opt b/gcc/common.opt index 520fa9c..bbf79ef 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -2451,6 +2451,11 @@ fsplit-paths Common Report Var(flag_split_paths) Init(0) Optimization Split paths leading to loop backedges. +funconstrained-commons +Common Var(flag_unconstrained_commons) Optimization +Assume common declarations may be overridden with ones with a larger +trailing array. + funit-at-a-time Common Report Var(flag_unit_at_a_time) Init(1) Compile whole compilation unit at a time. diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 0a2a6f4..68933a1 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -407,7 +407,7 @@ Objective-C and Objective-C++ Dialects}. -ftree-parallelize-loops=@var{n} -ftree-pre -ftree-partial-pre -ftree-pta @gol -ftree-reassoc -ftree-sink -ftree-slsr -ftree-sra @gol -ftree-switch-conversion -ftree-tail-merge -ftree-ter @gol --ftree-vectorize -ftree-vrp @gol +-ftree-vectorize -ftree-vrp -funconstrained-commons @gol -funit-at-a-time -funroll-all-loops -funroll-loops @gol -funsafe-loop-optimizations -funsafe-math-optimizations -funswitch-loops @gol -fipa-ra -fvariable-expansion-in-unroller -fvect-cost-model -fvpt @gol @@ -6659,6 +6659,12 @@ the loop optimizer itself cannot prove that these assumptions are valid. If you use @option{-Wunsafe-loop-optimizations}, the compiler warns you if it finds this kind of loop. +@item -funconstrained-commons +@opindex funconstrained-commons +This option tells the compiler that variables declared in common blocks +(e.g. Fortran) may later be overridden with longer trailing arrays. This +prevents certain optimizations that depend on knowing the array bounds. + @item -fcrossjumping @opindex fcrossjumping Perform cross-jumping transformation. diff --git a/gcc/testsuite/gfortran.dg/unconstrained_commons.f b/gcc/testsuite/gfortran.dg/unconstrained_commons.f new file mode 100644 index 0000000..f9fc471 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/unconstrained_commons.f @@ -0,0 +1,20 @@ +! { dg-do compile } +! { dg-options "-O3 -funconstrained-commons -fdump-tree-dom2-details" } + +! Test for PR69368: a single-element array in a common block, which will be +! overridden with a larger size at link time (contrary to language spec). +! Dominator opts considers accesses to differently-computed elements of X as +! equivalent, unless -funconstrained-commons is passed in. + SUBROUTINE FOO + IMPLICIT DOUBLE PRECISION (X) + INTEGER J + COMMON /MYCOMMON / X(1) + DO 10 J=1,1024 + X(J+1)=X(J+7) + 10 CONTINUE + RETURN + END +! { dg-final { scan-tree-dump-not "FIND" "dom2" } } +! We should retain both a read and write of mycommon.x. +! { dg-final { scan-tree-dump-times " _\[0-9\]+ = mycommon\\.x\\\[_\[0-9\]+\\\];" 1 "dom2" } } +! { dg-final { scan-tree-dump-times " mycommon\\.x\\\[_\[0-9\]+\\\] = _\[0-9\]+;" 1 "dom2" } } diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c index 0e98056..f133abc 100644 --- a/gcc/tree-dfa.c +++ b/gcc/tree-dfa.c @@ -612,9 +612,22 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset, if (DECL_P (exp)) { + if (flag_unconstrained_commons + && TREE_CODE (exp) == VAR_DECL && DECL_COMMON (exp)) + { + tree sz_tree = TYPE_SIZE (TREE_TYPE (exp)); + /* If size is unknown, or we have read to the end, assume there + may be more to the structure than we are told. */ + if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE + || (seen_variable_array_ref + && (sz_tree == NULL_TREE + || TREE_CODE (sz_tree) != INTEGER_CST + || (bit_offset + maxsize == wi::to_offset (sz_tree))))) + maxsize = -1; + } /* If maxsize is unknown adjust it according to the size of the base decl. */ - if (maxsize == -1 + else if (maxsize == -1 && DECL_SIZE (exp) && TREE_CODE (DECL_SIZE (exp)) == INTEGER_CST) maxsize = wi::to_offset (DECL_SIZE (exp)) - bit_offset; diff --git a/gcc/tree.c b/gcc/tree.c index 07cb9d9..9179b37 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -12957,8 +12957,10 @@ array_at_struct_end_p (tree ref) } /* If the reference is based on a declared entity, the size of the array - is constrained by its given domain. */ - if (DECL_P (ref)) + is constrained by its given domain. (Do not trust commons PR/69368). */ + if (DECL_P (ref) + && !(flag_unconstrained_commons + && TREE_CODE (ref) == VAR_DECL && DECL_COMMON (ref))) return false; return true;