diff mbox

Add -funconstrained-commons to work around PR/69368 (and others) in SPEC2006 (was: Re: [PATCH] Add -funknown-commons ...)

Message ID 1457348563-3326-1-git-send-email-alan.lawrence@arm.com
State New
Headers show

Commit Message

Alan Lawrence March 7, 2016, 11:02 a.m. UTC
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.

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

Comments

Alan Lawrence March 9, 2016, 5:54 p.m. UTC | #1
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;
>
Richard Biener March 10, 2016, 10:51 a.m. UTC | #2
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 mbox

Patch

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;