diff options
author | Alan Modra <amodra@gmail.com> | 2015-04-28 13:17:19 +0930 |
---|---|---|
committer | Alan Modra <amodra@gcc.gnu.org> | 2015-04-28 13:17:19 +0930 |
commit | 3954ead0d88676855e877a8a20c05f49256260d7 (patch) | |
tree | a4a4eb35291c72c4e8e3667ec61ef8760b899aa6 /gcc | |
parent | 1a9f259288745633d1cec9991b55c08dfae2669b (diff) | |
download | gcc-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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/config.in | 6 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 57 | ||||
-rwxr-xr-x | gcc/configure | 34 | ||||
-rw-r--r-- | gcc/configure.ac | 25 |
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 |