diff options
author | Richard Henderson <rth@redhat.com> | 2012-09-10 06:08:18 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2012-09-10 06:08:18 -0700 |
commit | d75171f35f62918f604ab856643cac9f691b237c (patch) | |
tree | 87194a56f45c6d8088d3a324d8034315f468c6ab /gcc | |
parent | 30d32ae6b63e34152700a9b7b8b41cc85a5774c8 (diff) | |
download | gcc-d75171f35f62918f604ab856643cac9f691b237c.zip gcc-d75171f35f62918f604ab856643cac9f691b237c.tar.gz gcc-d75171f35f62918f604ab856643cac9f691b237c.tar.bz2 |
* config/alpha/predicates.md (small_symbolic_operand): Disallow large offsets.
From-SVN: r191138
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/config/alpha/predicates.md | 40 |
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 |