re PR target/65810 (powerpc64 alignment of r2 insufficient for loading long-double...
authorAlan Modra <amodra@gmail.com>
Tue, 28 Apr 2015 03:47:19 +0000 (13:17 +0930)
committerAlan Modra <amodra@gcc.gnu.org>
Tue, 28 Apr 2015 03:47:19 +0000 (13:17 +0930)
PR target/65810
* config/rs6000/rs6000.c (POWERPC64_TOC_POINTER_ALIGNMENT): Define.
(offsettable_ok_by_alignment): Use minimum of decl and toc
pointer alignment.  Replace dead code with assertion.
(use_toc_relative_ref): Add mode arg.  Return false in -mcmodel=medium
case if size exceeds toc pointer alignment.
(rs6000_legitimize_reload_address): Update use_toc_relative_ref call.
(rs6000_emit_move): Likewise.
* configure.ac: Add linker toc pointer alignment check.
* configure: Regenerate.
* config.in: Regenerate.

From-SVN: r222498

gcc/ChangeLog
gcc/config.in
gcc/config/rs6000/rs6000.c
gcc/configure
gcc/configure.ac

index a24e57c65ce6cac3c82d74c0461d388372a139cf..fff0015a15fc7a036233d1ad3d9984b6555af56a 100644 (file)
@@ -1,3 +1,17 @@
+2015-04-28  Alan Modra  <amodra@gmail.com>
+
+       PR target/65810
+       * config/rs6000/rs6000.c (POWERPC64_TOC_POINTER_ALIGNMENT): Define.
+       (offsettable_ok_by_alignment): Use minimum of decl and toc
+       pointer alignment.  Replace dead code with assertion.
+       (use_toc_relative_ref): Add mode arg.  Return false in -mcmodel=medium
+       case if size exceeds toc pointer alignment.
+       (rs6000_legitimize_reload_address): Update use_toc_relative_ref call.
+       (rs6000_emit_move): Likewise.
+       * configure.ac: Add linker toc pointer alignment check.
+       * configure: Regenerate.
+       * config.in: Regenerate.
+
 2015-04-27  Yoshinori Sato <ysato@users.sourceforge.jp>
 
        * config.gcc: Add h8300-*-linux.
index f2ed301a48023c34378998c3ee8fc205d1212aa6..231c9abe712bfd244e96d70b8bc200783d1e3450 100644 (file)
 #endif
 
 
+/* Define to .TOC. alignment forced by your linker. */
+#ifndef USED_FOR_TARGET
+#undef POWERPC64_TOC_POINTER_ALIGNMENT
+#endif
+
+
 /* Define to PREFIX/include if cpp should also search that directory. */
 #ifndef USED_FOR_TARGET
 #undef PREFIX_INCLUDE_DIR
index 3245d46af63552e2c3b060a4c22877116d175add..c74c7d14b87da848174ba9a4b83cef9ed1b08f68 100644 (file)
@@ -6524,13 +6524,21 @@ virtual_stack_registers_memory_p (rtx op)
 }
 
 /* Return true if a MODE sized memory accesses to OP plus OFFSET
-   is known to not straddle a 32k boundary.  */
+   is known to not straddle a 32k boundary.  This function is used
+   to determine whether -mcmodel=medium code can use TOC pointer
+   relative addressing for OP.  This means the alignment of the TOC
+   pointer must also be taken into account, and unfortunately that is
+   only 8 bytes.  */ 
+
+#ifndef POWERPC64_TOC_POINTER_ALIGNMENT
+#define POWERPC64_TOC_POINTER_ALIGNMENT 8
+#endif
 
 static bool
 offsettable_ok_by_alignment (rtx op, HOST_WIDE_INT offset,
                             machine_mode mode)
 {
-  tree decl, type;
+  tree decl;
   unsigned HOST_WIDE_INT dsize, dalign, lsb, mask;
 
   if (GET_CODE (op) != SYMBOL_REF)
@@ -6583,38 +6591,20 @@ offsettable_ok_by_alignment (rtx op, HOST_WIDE_INT offset,
          if (dsize > 32768)
            return false;
 
-         return dalign / BITS_PER_UNIT >= dsize;
+         dalign /= BITS_PER_UNIT;
+         if (dalign > POWERPC64_TOC_POINTER_ALIGNMENT)
+           dalign = POWERPC64_TOC_POINTER_ALIGNMENT;
+         return dalign >= dsize;
        }
     }
   else
-    {
-      type = TREE_TYPE (decl);
-
-      dalign = TYPE_ALIGN (type);
-      if (CONSTANT_CLASS_P (decl))
-       dalign = CONSTANT_ALIGNMENT (decl, dalign);
-      else
-       dalign = DATA_ALIGNMENT (decl, dalign);
-
-      if (dsize == 0)
-       {
-         /* BLKmode, check the entire object.  */
-         if (TREE_CODE (decl) == STRING_CST)
-           dsize = TREE_STRING_LENGTH (decl);
-         else if (TYPE_SIZE_UNIT (type)
-                  && tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)))
-           dsize = tree_to_uhwi (TYPE_SIZE_UNIT (type));
-         else
-           return false;
-         if (dsize > 32768)
-           return false;
-
-         return dalign / BITS_PER_UNIT >= dsize;
-       }
-    }
+    gcc_unreachable ();
 
   /* Find how many bits of the alignment we know for this access.  */
-  mask = dalign / BITS_PER_UNIT - 1;
+  dalign /= BITS_PER_UNIT;
+  if (dalign > POWERPC64_TOC_POINTER_ALIGNMENT)
+    dalign = POWERPC64_TOC_POINTER_ALIGNMENT;
+  mask = dalign - 1;
   lsb = offset & -offset;
   mask &= lsb - 1;
   dalign = mask + 1;
@@ -7553,13 +7543,14 @@ rs6000_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
    can be addressed relative to the toc pointer.  */
 
 static bool
-use_toc_relative_ref (rtx sym)
+use_toc_relative_ref (rtx sym, machine_mode mode)
 {
   return ((constant_pool_expr_p (sym)
           && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (sym),
                                               get_pool_mode (sym)))
          || (TARGET_CMODEL == CMODEL_MEDIUM
-             && SYMBOL_REF_LOCAL_P (sym)));
+             && SYMBOL_REF_LOCAL_P (sym)
+             && GET_MODE_SIZE (mode) <= POWERPC64_TOC_POINTER_ALIGNMENT));
 }
 
 /* Our implementation of LEGITIMIZE_RELOAD_ADDRESS.  Returns a value to
@@ -7764,7 +7755,7 @@ rs6000_legitimize_reload_address (rtx x, machine_mode mode,
   if (TARGET_TOC
       && reg_offset_p
       && GET_CODE (x) == SYMBOL_REF
-      && use_toc_relative_ref (x))
+      && use_toc_relative_ref (x, mode))
     {
       x = create_TOC_reference (x, NULL_RTX);
       if (TARGET_CMODEL != CMODEL_SMALL)
@@ -8842,7 +8833,7 @@ rs6000_emit_move (rtx dest, rtx source, machine_mode mode)
         reference to it.  */
       if (TARGET_TOC
          && GET_CODE (operands[1]) == SYMBOL_REF
-         && use_toc_relative_ref (operands[1]))
+         && use_toc_relative_ref (operands[1], mode))
        operands[1] = create_TOC_reference (operands[1], operands[0]);
       else if (mode == Pmode
               && CONSTANT_P (operands[1])
index 9523773e721bd8dd162aca96671a29d037bc10c2..84f58ce35d2fd7b3e41d3f714bfacfb0c10ad4a7 100755 (executable)
@@ -27530,6 +27530,40 @@ $as_echo "$gcc_cv_ld_large_toc" >&6; }
 
 $as_echo "#define HAVE_LD_LARGE_TOC 1" >>confdefs.h
 
+    fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking linker toc pointer alignment" >&5
+$as_echo_n "checking linker toc pointer alignment... " >&6; }
+if test "${gcc_cv_ld_toc_align+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_nm != x; then
+      cat > conftest.s <<EOF
+       .global _start
+       .text
+_start:
+       addis 9,2,x@got@ha
+       .section .data.rel.ro,"aw",@progbits
+       .p2align 16
+       .space 32768
+x:     .quad .TOC.
+EOF
+      if $gcc_cv_as -a64 -o conftest.o conftest.s > /dev/null 2>&1 \
+         && $gcc_cv_ld $emul_name -o conftest conftest.o > /dev/null 2>&1; then
+        gcc_cv_ld_toc_align=`$gcc_cv_nm conftest | ${AWK} '/\.TOC\./ { match ($0, "0[[:xdigit:]]*", a); print strtonum ("0x" substr(a[0], length(a[0])-3)) }'`
+      fi
+      rm -f conftest conftest.o conftest.s
+    fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_toc_align" >&5
+$as_echo "$gcc_cv_ld_toc_align" >&6; }
+    if test -n "$gcc_cv_ld_toc_align" && test $gcc_cv_ld_toc_align -gt 8; then
+
+cat >>confdefs.h <<_ACEOF
+#define POWERPC64_TOC_POINTER_ALIGNMENT $gcc_cv_ld_toc_align
+_ACEOF
+
     fi
     ;;
 esac
index 68b0ee83fac8be32fcc4618003f489c211eeae5a..7fb61312f3f7ad468356862824644da06e73ed2d 100644 (file)
@@ -5087,6 +5087,31 @@ EOF
       AC_DEFINE(HAVE_LD_LARGE_TOC, 1,
     [Define if your PowerPC64 linker supports a large TOC.])
     fi
+
+    AC_CACHE_CHECK(linker toc pointer alignment,
+    gcc_cv_ld_toc_align,
+    [if test x$gcc_cv_as != x -a x$gcc_cv_ld != x -a x$gcc_cv_nm != x; then
+      cat > conftest.s <<EOF
+       .global _start
+       .text
+_start:
+       addis 9,2,x@got@ha
+       .section .data.rel.ro,"aw",@progbits
+       .p2align 16
+       .space 32768
+x:     .quad .TOC.
+EOF
+      if $gcc_cv_as -a64 -o conftest.o conftest.s > /dev/null 2>&1 \
+         && $gcc_cv_ld $emul_name -o conftest conftest.o > /dev/null 2>&1; then
+        gcc_cv_ld_toc_align=`$gcc_cv_nm conftest | ${AWK} '/\.TOC\./ { match ($0, "0[[[:xdigit:]]]*", a); print strtonum ("0x" substr(a[[0]], length(a[[0]])-3)) }'`
+      fi
+      rm -f conftest conftest.o conftest.s
+    fi
+    ])
+    if test -n "$gcc_cv_ld_toc_align" && test $gcc_cv_ld_toc_align -gt 8; then
+      AC_DEFINE_UNQUOTED(POWERPC64_TOC_POINTER_ALIGNMENT, $gcc_cv_ld_toc_align,
+    [Define to .TOC. alignment forced by your linker.])
+    fi
     ;;
 esac