This fixes a thinko in offsettable_ok_by_alignment. It's not the absolute placement that matters, but the toc-pointer relative offset. So alignment of r2 also needs to be taken into account.
Bootstrapped and regression tested powerpc64-linux. OK for mainline and gcc-5 branch? Without the dead code removal for the branch.. I also have a linker fix to align the toc pointer and gcc configury changes to supply POWERPC64_TOC_POINTER_ALIGNMENT in the works. PR target/65810 * config/rs6000/rs6000.c (POWERPC64_TOC_POINTER_ALIGNMENT): Define. (offsettable_ok_by_alignment): Return false if size exceeds POWERPC64_TOC_POINTER_ALIGNMENT. Replace dead code with assertion. Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 222227) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -6497,13 +6497,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) @@ -6510,6 +6518,8 @@ offsettable_ok_by_alignment (rtx op, HOST_WIDE_INT return false; dsize = GET_MODE_SIZE (mode); + if (dsize > POWERPC64_TOC_POINTER_ALIGNMENT) + return false; decl = SYMBOL_REF_DECL (op); if (!decl) { @@ -6553,6 +6563,8 @@ offsettable_ok_by_alignment (rtx op, HOST_WIDE_INT return false; dsize = tree_to_uhwi (DECL_SIZE_UNIT (decl)); + if (dsize > POWERPC64_TOC_POINTER_ALIGNMENT) + return false; if (dsize > 32768) return false; @@ -6560,32 +6572,8 @@ offsettable_ok_by_alignment (rtx op, HOST_WIDE_INT } } else - { - type = TREE_TYPE (decl); + gcc_unreachable (); - 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; - } - } - /* Find how many bits of the alignment we know for this access. */ mask = dalign / BITS_PER_UNIT - 1; lsb = offset & -offset; -- Alan Modra Australia Development Lab, IBM