aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2012-09-10 06:08:18 -0700
committerRichard Henderson <rth@gcc.gnu.org>2012-09-10 06:08:18 -0700
commitd75171f35f62918f604ab856643cac9f691b237c (patch)
tree87194a56f45c6d8088d3a324d8034315f468c6ab
parent30d32ae6b63e34152700a9b7b8b41cc85a5774c8 (diff)
downloadgcc-d75171f35f62918f604ab856643cac9f691b237c.zip
gcc-d75171f35f62918f604ab856643cac9f691b237c.tar.gz
gcc-d75171f35f62918f604ab856643cac9f691b237c.tar.bz2
* config/alpha/predicates.md (small_symbolic_operand): Disallow large offsets.
From-SVN: r191138
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/config/alpha/predicates.md40
2 files changed, 37 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c53ed7b..6e7175a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2012-09-10 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/predicates.md (small_symbolic_operand): Disallow
+ large offsets.
+
2012-09-10 Georg-Johann Lay <avr@gjlay.de>
PR target/54536
diff --git a/gcc/config/alpha/predicates.md b/gcc/config/alpha/predicates.md
index 598742f..0a1885b 100644
--- a/gcc/config/alpha/predicates.md
+++ b/gcc/config/alpha/predicates.md
@@ -328,26 +328,50 @@
(define_predicate "small_symbolic_operand"
(match_code "const,symbol_ref")
{
+ HOST_WIDE_INT ofs = 0, max_ofs = 0;
+
if (! TARGET_SMALL_DATA)
- return 0;
+ return false;
if (GET_CODE (op) == CONST
&& GET_CODE (XEXP (op, 0)) == PLUS
&& CONST_INT_P (XEXP (XEXP (op, 0), 1)))
- op = XEXP (XEXP (op, 0), 0);
+ {
+ ofs = INTVAL (XEXP (XEXP (op, 0), 1));
+ op = XEXP (XEXP (op, 0), 0);
+ }
if (GET_CODE (op) != SYMBOL_REF)
- return 0;
+ return false;
/* ??? There's no encode_section_info equivalent for the rtl
constant pool, so SYMBOL_FLAG_SMALL never gets set. */
if (CONSTANT_POOL_ADDRESS_P (op))
- return GET_MODE_SIZE (get_pool_mode (op)) <= g_switch_value;
+ {
+ max_ofs = GET_MODE_SIZE (get_pool_mode (op));
+ if (max_ofs > g_switch_value)
+ return false;
+ }
+ else if (SYMBOL_REF_LOCAL_P (op)
+ && SYMBOL_REF_SMALL_P (op)
+ && !SYMBOL_REF_WEAK (op)
+ && !SYMBOL_REF_TLS_MODEL (op))
+ {
+ if (SYMBOL_REF_DECL (op))
+ max_ofs = tree_low_cst (DECL_SIZE_UNIT (SYMBOL_REF_DECL (op)), 1);
+ }
+ else
+ return false;
- return (SYMBOL_REF_LOCAL_P (op)
- && SYMBOL_REF_SMALL_P (op)
- && !SYMBOL_REF_WEAK (op)
- && !SYMBOL_REF_TLS_MODEL (op));
+ /* Given that we know that the GP is always 8 byte aligned, we can
+ always adjust by 7 without overflowing. */
+ if (max_ofs < 8)
+ max_ofs = 8;
+
+ /* Since we know this is an object in a small data section, we know the
+ entire section is addressable via GP. We don't know where the section
+ boundaries are, but we know the entire object is within. */
+ return IN_RANGE (ofs, 0, max_ofs - 1);
})
;; Return true if OP is a SYMBOL_REF or CONST referencing a variable