aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2015-04-28 13:17:19 +0930
committerAlan Modra <amodra@gcc.gnu.org>2015-04-28 13:17:19 +0930
commit3954ead0d88676855e877a8a20c05f49256260d7 (patch)
treea4a4eb35291c72c4e8e3667ec61ef8760b899aa6
parent1a9f259288745633d1cec9991b55c08dfae2669b (diff)
downloadgcc-3954ead0d88676855e877a8a20c05f49256260d7.zip
gcc-3954ead0d88676855e877a8a20c05f49256260d7.tar.gz
gcc-3954ead0d88676855e877a8a20c05f49256260d7.tar.bz2
re PR target/65810 (powerpc64 alignment of r2 insufficient for loading long-double constants)
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
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/config.in6
-rw-r--r--gcc/config/rs6000/rs6000.c57
-rwxr-xr-xgcc/configure34
-rw-r--r--gcc/configure.ac25
5 files changed, 103 insertions, 33 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a24e57c..fff0015 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/config.in b/gcc/config.in
index f2ed301..231c9ab 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -1910,6 +1910,12 @@
#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
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 3245d46..c74c7d1 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -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])
diff --git a/gcc/configure b/gcc/configure
index 9523773..84f58ce 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -27531,6 +27531,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
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 68b0ee8..7fb6131 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -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