PR 80108 describes an ICE that occurs on an existing test program when
compiled with a particular combination of target options.

This patch fixes the compiler to reject that particular combination of
target options since it is not meaningful and duplicates the offending
test case with a dg-options directive to exercise the problematic
command-line options.

Thanks to feedback from Pat Haugen, Michael Meissner, and Segher
Boessenkool, version 2 of this proposed patch integrates the following
refinements:

1. Issue an error message when -mpower9-minmax is used in combination
   with -mcpu=power9 if specific prerequisite target options have been
   explicitly disabled.

2. Change the exclude-opts clause on the test case's dg-skip-if
   directive from -mcpu=power9 to -mcpu=405.  (This was a
   copy-and-paste error when this line was borrowed from a
   different test program.)

3. Remove -m32 from the dg-options directive.  Though this target
   option had been specified in the original problem report, subsequent
   testing confirmed that the original ICE occurs independent of this
   option.  Eliminating this option allows the regression test to be
   exercised in more more contexts.

This patch has been bootstrapped and tested with no regressions on both
powerpc64-unknown-linux-gnu and powerpc64le-unknown-linux-gnu.  Is
this ok for the trunk?

gcc/ChangeLog:

2017-04-06  Kelvin Nilsen  <kel...@gcc.gnu.org>

        PR target/80108
        * config/rs6000/rs6000.c (rs6000_option_override_internal):
        Enhance special handling given to the TARGET_P9_MINMAX option in
        relation to certain other options.

gcc/testsuite/ChangeLog:

2017-04-06  Kelvin Nilsen  <kel...@gcc.gnu.org>

        PR target/80108
        * gcc.target/powerpc/ppc-fortran/ppc-fortran.exp: New file.
        * gcc.target/powerpc/ppc-fortran/pr80108-1.f90: New test.

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c  (revision 246573)
+++ gcc/config/rs6000/rs6000.c  (working copy)
@@ -4273,8 +4273,40 @@ rs6000_option_override_internal (bool global_init_
   /* For the newer switches (vsx, dfp, etc.) set some of the older options,
      unless the user explicitly used the -mno-<option> to disable the code.  */
   if (TARGET_P9_VECTOR || TARGET_MODULO || TARGET_P9_DFORM_SCALAR
-      || TARGET_P9_DFORM_VECTOR || TARGET_P9_DFORM_BOTH > 0 || 
TARGET_P9_MINMAX)
+      || TARGET_P9_DFORM_VECTOR || TARGET_P9_DFORM_BOTH > 0)
     rs6000_isa_flags |= (ISA_3_0_MASKS_SERVER & ~rs6000_isa_flags_explicit);
+  else if (TARGET_P9_MINMAX)
+    {
+      if (have_cpu)
+       {
+         if (cpu_index == PROCESSOR_POWER9)
+           {
+             /* legacy behavior: allow -mcpu-power9 with certain
+                capabilities explicitly disabled.  */
+             rs6000_isa_flags |=
+               (ISA_3_0_MASKS_SERVER & ~rs6000_isa_flags_explicit);
+             /* However, reject this automatic fix if certain
+                capabilities required for TARGET_P9_MINMAX support
+                have been explicitly disabled.  */
+             if (((OPTION_MASK_VSX | OPTION_MASK_UPPER_REGS_SF
+                   | OPTION_MASK_UPPER_REGS_DF) & rs6000_isa_flags)
+                 != (OPTION_MASK_VSX | OPTION_MASK_UPPER_REGS_SF
+                      | OPTION_MASK_UPPER_REGS_DF))
+               error ("-mpower9-minmax incompatible with explicitly disabled 
options");
+               }
+         else
+           error ("Power9 target option is incompatible with -mcpu=<xxx> for "
+                  "<xxx> less than power9");
+       }
+      else if ((ISA_3_0_MASKS_SERVER & rs6000_isa_flags_explicit)
+              != (ISA_3_0_MASKS_SERVER & rs6000_isa_flags
+                  & rs6000_isa_flags_explicit))
+       /* Enforce that none of the ISA_3_0_MASKS_SERVER flags
+          were explicitly cleared.  */
+       error ("-mpower9-minmax incompatible with explicitly disabled options");
+      else
+       rs6000_isa_flags |= ISA_3_0_MASKS_SERVER;
+    }
   else if (TARGET_P8_VECTOR || TARGET_DIRECT_MOVE || TARGET_CRYPTO)
     rs6000_isa_flags |= (ISA_2_7_MASKS_SERVER & ~rs6000_isa_flags_explicit);
   else if (TARGET_VSX)
Index: gcc/testsuite/gcc.target/powerpc/ppc-fortran/ppc-fortran.exp
===================================================================
--- gcc/testsuite/gcc.target/powerpc/ppc-fortran/ppc-fortran.exp        
(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/ppc-fortran/ppc-fortran.exp        
(revision 246624)
@@ -0,0 +1,65 @@
+#   Copyright (C) 2004-2017 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Load support procs.
+load_lib gfortran-dg.exp
+
+# If a testcase doesn't have special options, use these.
+global DEFAULT_FFLAGS
+if ![info exists DEFAULT_FFLAGS] then {
+    set DEFAULT_FFLAGS " -pedantic-errors"
+}
+
+# Initialize `dg'.
+dg-init
+
+global gfortran_test_path
+global gfortran_aux_module_flags
+set gfortran_test_path $srcdir/$subdir
+set gfortran_aux_module_flags $DEFAULT_FFLAGS
+proc dg-compile-aux-modules { args } {
+    global gfortran_test_path
+    global gfortran_aux_module_flags
+    if { [llength $args] != 2 } {
+       error "dg-set-target-env-var: needs one argument"
+       return
+    }
+
+    set level [info level]
+    if { [info procs dg-save-unknown] != [list] } {
+       rename dg-save-unknown dg-save-unknown-level-$level
+    }
+
+    dg-test $gfortran_test_path/[lindex $args 1] "" $gfortran_aux_module_flags
+    # cleanup-modules is intentionally not invoked here.
+
+    if { [info procs dg-save-unknown-level-$level] != [list] } {
+       rename dg-save-unknown-level-$level dg-save-unknown
+    }
+}
+
+# Main loop.
+gfortran-dg-runtest [lsort \
+       [glob -nocomplain $srcdir/$subdir/*.\[fF\]{,90,95,03,08} ] ] "" 
$DEFAULT_FFLAGS
+
+gfortran-dg-runtest [lsort \
+       [glob -nocomplain $srcdir/$subdir/g77/*.\[fF\] ] ] "" $DEFAULT_FFLAGS
+
+
+# All done.
+dg-finish
Index: gcc/testsuite/gcc.target/powerpc/ppc-fortran/pr80108-1.f90
===================================================================
--- gcc/testsuite/gcc.target/powerpc/ppc-fortran/pr80108-1.f90  (revision 0)
+++ gcc/testsuite/gcc.target/powerpc/ppc-fortran/pr80108-1.f90  (working copy)
@@ -0,0 +1,53 @@
+! Originally contributed by Tobias Burnas.
+! { dg-do compile { target { powerpc*-*-* } } }
+! { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { 
"-mcpu=405" } }
+! { dg-require-effective-target powerpc_p9vector_ok }
+! { dg-options "-mcpu=405 -mpower9-minmax -mfloat128-type" }
+! { dg-excess-errors "expect error due to conflicting target options" }
+! Since the error message is not associated with a particular line
+! number, we cannot use the dg-error directive and cannot specify a
+! regexp to describe the expected error message.  The expected error
+! message is:
+!  "Power9 target option is incompatible with -mcpu=<xxx> for <xxx>
+!    less than power9"
+
+program stream_test
+    implicit none
+    character(len=*), parameter :: rec1 = 'record1'
+    character(len=*), parameter :: rec2 = 'record2'
+    character(len=50) :: str1,str2
+    integer           :: len, i
+    real              :: r
+
+    open(10,form='formatted',access='stream',&
+         status='scratch',position='rewind')
+    write(10,'(a)') rec1//new_line('a')//rec2
+    rewind(10)
+    read(10,*) str1
+    read(10,*) str2
+    if(str1 /= rec1 .or. str2 /= rec2) call abort()
+    rewind(10)
+    read(10,'(a)') str1
+    read(10,'(a)') str2
+    if(str1 /= rec1 .or. str2 /= rec2) call abort()
+    close(10)
+
+    open(10,form='formatted',access='stream',&
+         status='scratch',position='rewind')
+    write(10,*) '123 '//trim(rec1)//'  1e-12'
+    write(10,*) '12345.6789'
+    rewind(10)
+    read(10,*) i,str1
+    read(10,*) r
+    if(i /= 123 .or. str1 /= rec1 .or. r /= 12345.6789) &
+      call abort()
+    close(10)
+
+    open(unit=10,form='unformatted',access='stream', &
+         status='scratch',position='rewind')
+    write(10) rec1//new_line('a')//rec2
+    len = len_trim(rec1//new_line('a')//rec2)
+    rewind(10)
+    read(10) str1(1:len)
+    if(str1 /= rec1//new_line('a')//rec2) call abort()
+end program stream_test

Reply via email to