aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2013-06-07 14:26:46 +0930
committerAlan Modra <amodra@gcc.gnu.org>2013-06-07 14:26:46 +0930
commitacd17ae6c85a4c094f1360632732c7a5ae058ecc (patch)
tree48979d1bafcba8bed947a49c8c9403a0a25c6b6f
parenta9429737bda029bc8e668e23986e2d75fcec255f (diff)
downloadgcc-acd17ae6c85a4c094f1360632732c7a5ae058ecc.zip
gcc-acd17ae6c85a4c094f1360632732c7a5ae058ecc.tar.gz
gcc-acd17ae6c85a4c094f1360632732c7a5ae058ecc.tar.bz2
rs6000.c (rs6000_option_override_internal): Don't override user -mfp-in-toc.
* config/rs6000/rs6000.c (rs6000_option_override_internal): Don't override user -mfp-in-toc. (offsettable_ok_by_alignment): Consider just the current access rather than the whole object, unless BLKmode. Handle CONSTANT_POOL_ADDRESS_P constants that lack a decl too. (use_toc_relative_ref): Allow CONSTANT_POOL_ADDRESS_P constants for -mcmodel=medium. * config/rs6000/linux64.h (SUBSUBTARGET_OVERRIDE_OPTIONS): Don't override user -mfp-in-toc or -msum-in-toc. Default to -mno-fp-in-toc for -mcmodel=medium. From-SVN: r199781
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/config/rs6000/linux64.h7
-rw-r--r--gcc/config/rs6000/rs6000.c107
3 files changed, 77 insertions, 50 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b604c2c..99db65a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+2013-06-07 Alan Modra <amodra@gmail.com>
+
+ * config/rs6000/rs6000.c (rs6000_option_override_internal): Don't
+ override user -mfp-in-toc.
+ (offsettable_ok_by_alignment): Consider just the current access
+ rather than the whole object, unless BLKmode. Handle
+ CONSTANT_POOL_ADDRESS_P constants that lack a decl too.
+ (use_toc_relative_ref): Allow CONSTANT_POOL_ADDRESS_P constants
+ for -mcmodel=medium.
+ * config/rs6000/linux64.h (SUBSUBTARGET_OVERRIDE_OPTIONS): Don't
+ override user -mfp-in-toc or -msum-in-toc. Default to
+ -mno-fp-in-toc for -mcmodel=medium.
+
2013-06-06 DJ Delorie <dj@redhat.com>
* config/rl78/rl78.c (rl78_valid_pointer_mode): New, implements
diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h
index 3f28058..79f0f0b 100644
--- a/gcc/config/rs6000/linux64.h
+++ b/gcc/config/rs6000/linux64.h
@@ -136,8 +136,11 @@ extern int dot_symbols;
SET_CMODEL (CMODEL_MEDIUM); \
if (rs6000_current_cmodel != CMODEL_SMALL) \
{ \
- TARGET_NO_FP_IN_TOC = 0; \
- TARGET_NO_SUM_IN_TOC = 0; \
+ if (!global_options_set.x_TARGET_NO_FP_IN_TOC) \
+ TARGET_NO_FP_IN_TOC \
+ = rs6000_current_cmodel == CMODEL_MEDIUM; \
+ if (!global_options_set.x_TARGET_NO_SUM_IN_TOC) \
+ TARGET_NO_SUM_IN_TOC = 0; \
} \
} \
} \
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 161fd6b..cc16e3f 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -3052,7 +3052,8 @@ rs6000_option_override_internal (bool global_init_p)
/* Place FP constants in the constant pool instead of TOC
if section anchors enabled. */
- if (flag_section_anchors)
+ if (flag_section_anchors
+ && !global_options_set.x_TARGET_NO_FP_IN_TOC)
TARGET_NO_FP_IN_TOC = 1;
if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
@@ -5519,91 +5520,102 @@ virtual_stack_registers_memory_p (rtx op)
&& regnum <= LAST_VIRTUAL_POINTER_REGISTER);
}
-/* Return true if memory accesses to OP are known to never straddle
- a 32k boundary. */
+/* Return true if a MODE sized memory accesses to OP plus OFFSET
+ is known to not straddle a 32k boundary. */
static bool
offsettable_ok_by_alignment (rtx op, HOST_WIDE_INT offset,
enum machine_mode mode)
{
tree decl, type;
- unsigned HOST_WIDE_INT dsize, dalign;
+ unsigned HOST_WIDE_INT dsize, dalign, lsb, mask;
if (GET_CODE (op) != SYMBOL_REF)
return false;
+ dsize = GET_MODE_SIZE (mode);
decl = SYMBOL_REF_DECL (op);
if (!decl)
{
- if (GET_MODE_SIZE (mode) == 0)
+ if (dsize == 0)
return false;
/* -fsection-anchors loses the original SYMBOL_REF_DECL when
replacing memory addresses with an anchor plus offset. We
could find the decl by rummaging around in the block->objects
VEC for the given offset but that seems like too much work. */
- dalign = 1;
+ dalign = BITS_PER_UNIT;
if (SYMBOL_REF_HAS_BLOCK_INFO_P (op)
&& SYMBOL_REF_ANCHOR_P (op)
&& SYMBOL_REF_BLOCK (op) != NULL)
{
struct object_block *block = SYMBOL_REF_BLOCK (op);
- HOST_WIDE_INT lsb, mask;
- /* Given the alignment of the block.. */
dalign = block->alignment;
- mask = dalign / BITS_PER_UNIT - 1;
-
- /* ..and the combined offset of the anchor and any offset
- to this block object.. */
offset += SYMBOL_REF_BLOCK_OFFSET (op);
- lsb = offset & -offset;
+ }
+ else if (CONSTANT_POOL_ADDRESS_P (op))
+ {
+ /* It would be nice to have get_pool_align().. */
+ enum machine_mode cmode = get_pool_mode (op);
- /* ..find how many bits of the alignment we know for the
- object. */
- mask &= lsb - 1;
- dalign = mask + 1;
+ dalign = GET_MODE_ALIGNMENT (cmode);
}
- return dalign >= GET_MODE_SIZE (mode);
}
-
- if (DECL_P (decl))
+ else if (DECL_P (decl))
{
- if (TREE_CODE (decl) == FUNCTION_DECL)
- return true;
+ dalign = DECL_ALIGN (decl);
- if (!DECL_SIZE_UNIT (decl))
- return false;
+ if (dsize == 0)
+ {
+ /* Allow BLKmode when the entire object is known to not
+ cross a 32k boundary. */
+ if (!DECL_SIZE_UNIT (decl))
+ return false;
- if (!host_integerp (DECL_SIZE_UNIT (decl), 1))
- return false;
+ if (!host_integerp (DECL_SIZE_UNIT (decl), 1))
+ return false;
- dsize = tree_low_cst (DECL_SIZE_UNIT (decl), 1);
- if (dsize > 32768)
- return false;
+ dsize = tree_low_cst (DECL_SIZE_UNIT (decl), 1);
+ if (dsize > 32768)
+ return false;
- dalign = DECL_ALIGN_UNIT (decl);
- return dalign >= dsize;
+ return dalign / BITS_PER_UNIT >= dsize;
+ }
}
+ else
+ {
+ type = TREE_TYPE (decl);
- 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 (TREE_CODE (decl) == STRING_CST)
- dsize = TREE_STRING_LENGTH (decl);
- else if (TYPE_SIZE_UNIT (type)
- && host_integerp (TYPE_SIZE_UNIT (type), 1))
- dsize = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
- else
- return false;
- if (dsize > 32768)
- return false;
+ 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)
+ && host_integerp (TYPE_SIZE_UNIT (type), 1))
+ dsize = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
+ 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;
+ mask &= lsb - 1;
+ dalign = mask + 1;
- dalign = TYPE_ALIGN (type);
- if (CONSTANT_CLASS_P (decl))
- dalign = CONSTANT_ALIGNMENT (decl, dalign);
- else
- dalign = DATA_ALIGNMENT (decl, dalign);
- dalign /= BITS_PER_UNIT;
return dalign >= dsize;
}
@@ -6549,7 +6561,6 @@ use_toc_relative_ref (rtx sym)
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (sym),
get_pool_mode (sym)))
|| (TARGET_CMODEL == CMODEL_MEDIUM
- && !CONSTANT_POOL_ADDRESS_P (sym)
&& SYMBOL_REF_LOCAL_P (sym)));
}