diff options
author | Robin Dapp <rdapp@linux.vnet.ibm.com> | 2015-11-23 08:05:33 +0000 |
---|---|---|
committer | Andreas Krebbel <krebbel@gcc.gnu.org> | 2015-11-23 08:05:33 +0000 |
commit | e63d44c2a9d2a95c7f23de189966be0a3dcc5923 (patch) | |
tree | f06f2517d73d42a2b0cfdbbf9e92039a2fbf3069 /gcc/config/s390 | |
parent | 6e9966e8303f5f39870a11d96a64b376a2fab347 (diff) | |
download | gcc-e63d44c2a9d2a95c7f23de189966be0a3dcc5923.zip gcc-e63d44c2a9d2a95c7f23de189966be0a3dcc5923.tar.gz gcc-e63d44c2a9d2a95c7f23de189966be0a3dcc5923.tar.bz2 |
S/390: Fix symbol ref alignment
This patch fixes the treatment of symbol ref alignments for
arrays and structs in S390. Until now, the NOT_NATURALLY_ALIGNED flag
was not correctly set for array elements and structs larger than 8
bytes. Therefore, load relative instructions that require a specific
alignment would not always be generated. This patch uses separate flags
for 2-, 4-, and 8-byte alignment to fix the problem.
gcc/testsuite/ChangeLog:
2015-11-23 Robin Dapp <rdapp@linux.vnet.ibm.com>
* gcc.target/s390/load-relative-check.c: New test to check
generation of load relative instructions.
gcc/ChangeLog:
2015-11-23 Robin Dapp <rdapp@linux.vnet.ibm.com>
* config/s390/s390.h: Add new symref flags, _NOTALIGN2 etc.
* config/s390/s390.c (s390_check_symref_alignment): Use new
symref flags, early abort on wrong alignment
(s390_secondary_reload): Use new symref flags.
(s390_encode_section_info): Likewise.
* config/s390/predicates.md: Likewise.
From-SVN: r230735
Diffstat (limited to 'gcc/config/s390')
-rw-r--r-- | gcc/config/s390/predicates.md | 4 | ||||
-rw-r--r-- | gcc/config/s390/s390.c | 65 | ||||
-rw-r--r-- | gcc/config/s390/s390.h | 35 |
3 files changed, 76 insertions, 28 deletions
diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md index eeaf1ae..893092b 100644 --- a/gcc/config/s390/predicates.md +++ b/gcc/config/s390/predicates.md @@ -122,7 +122,7 @@ if (GET_CODE (op) == LABEL_REF) return true; if (GET_CODE (op) == SYMBOL_REF) - return (!SYMBOL_REF_ALIGN1_P (op) + return (!SYMBOL_FLAG_NOTALIGN2_P (op) && SYMBOL_REF_TLS_MODEL (op) == 0 && (!flag_pic || SYMBOL_REF_LOCAL_P (op))); @@ -147,7 +147,7 @@ if (GET_CODE (op) == LABEL_REF) return true; if (GET_CODE (op) == SYMBOL_REF) - return ((SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_ALIGN1) == 0 + return (!SYMBOL_FLAG_NOTALIGN2_P (op) && SYMBOL_REF_TLS_MODEL (op) == 0 && (!flag_pic || SYMBOL_REF_LOCAL_P (op))); diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 40ee2f7..5a7406c 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -3922,15 +3922,30 @@ s390_check_symref_alignment (rtx addr, HOST_WIDE_INT alignment) HOST_WIDE_INT addend; rtx symref; + /* The "required alignment" might be 0 (e.g. for certain structs + accessed via BLKmode). Early abort in this case, as well as when + an alignment > 8 is required. */ + if (alignment < 2 || alignment > 8) + return false; + if (!s390_loadrelative_operand_p (addr, &symref, &addend)) return false; if (addend & (alignment - 1)) return false; - if (GET_CODE (symref) == SYMBOL_REF - && !SYMBOL_REF_NOT_NATURALLY_ALIGNED_P (symref)) - return true; + if (GET_CODE (symref) == SYMBOL_REF) + { + /* We have load-relative instructions for 2-byte, 4-byte, and + 8-byte alignment so allow only these. */ + switch (alignment) + { + case 8: return !SYMBOL_FLAG_NOTALIGN8_P (symref); + case 4: return !SYMBOL_FLAG_NOTALIGN4_P (symref); + case 2: return !SYMBOL_FLAG_NOTALIGN2_P (symref); + default: return false; + } + } if (GET_CODE (symref) == UNSPEC && alignment <= UNITS_PER_LONG) @@ -4062,7 +4077,7 @@ s390_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i, if (in_p && s390_loadrelative_operand_p (x, &symref, &offset) && mode == Pmode - && !SYMBOL_REF_ALIGN1_P (symref) + && !SYMBOL_FLAG_NOTALIGN2_P (symref) && (offset & 1) == 1) sri->icode = ((mode == DImode) ? CODE_FOR_reloaddi_larl_odd_addend_z10 : CODE_FOR_reloadsi_larl_odd_addend_z10); @@ -11813,29 +11828,39 @@ s390_encode_section_info (tree decl, rtx rtl, int first) if (TREE_CODE (decl) == VAR_DECL) { - /* If a variable has a forced alignment to < 2 bytes, mark it - with SYMBOL_FLAG_ALIGN1 to prevent it from being used as LARL - operand. */ - if (DECL_USER_ALIGN (decl) && DECL_ALIGN (decl) < 16) - SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_ALIGN1; - if (!DECL_SIZE (decl) - || !DECL_ALIGN (decl) - || !tree_fits_shwi_p (DECL_SIZE (decl)) - || (DECL_ALIGN (decl) <= 64 - && DECL_ALIGN (decl) != tree_to_shwi (DECL_SIZE (decl)))) - SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_NOT_NATURALLY_ALIGNED; + /* Store the alignment to be able to check if we can use + a larl/load-relative instruction. We only handle the cases + that can go wrong (i.e. no FUNC_DECLs). If a symref does + not have any flag we assume it to be correctly aligned. */ + + if (DECL_ALIGN (decl) % 64) + SYMBOL_FLAG_SET_NOTALIGN8 (XEXP (rtl, 0)); + + if (DECL_ALIGN (decl) % 32) + SYMBOL_FLAG_SET_NOTALIGN4 (XEXP (rtl, 0)); + + if (DECL_ALIGN (decl) == 0 || DECL_ALIGN (decl) % 16) + SYMBOL_FLAG_SET_NOTALIGN2 (XEXP (rtl, 0)); } /* Literal pool references don't have a decl so they are handled differently here. We rely on the information in the MEM_ALIGN - entry to decide upon natural alignment. */ + entry to decide upon the alignment. */ if (MEM_P (rtl) && GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF && TREE_CONSTANT_POOL_ADDRESS_P (XEXP (rtl, 0)) - && (MEM_ALIGN (rtl) == 0 - || GET_MODE_BITSIZE (GET_MODE (rtl)) == 0 - || MEM_ALIGN (rtl) < GET_MODE_BITSIZE (GET_MODE (rtl)))) - SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_NOT_NATURALLY_ALIGNED; + && MEM_ALIGN (rtl) != 0 + && GET_MODE_BITSIZE (GET_MODE (rtl)) != 0) + { + if (MEM_ALIGN (rtl) % 64) + SYMBOL_FLAG_SET_NOTALIGN8 (XEXP (rtl, 0)); + + if (MEM_ALIGN (rtl) % 32) + SYMBOL_FLAG_SET_NOTALIGN4 (XEXP (rtl, 0)); + + if (MEM_ALIGN (rtl) == 0 || MEM_ALIGN (rtl) % 16) + SYMBOL_FLAG_SET_NOTALIGN2 (XEXP (rtl, 0)); + } } /* Output thunk to FILE that implements a C++ virtual function call (with diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index a0faf13ba..0f9225c 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h @@ -963,12 +963,35 @@ do { \ #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 64, 1) /* Machine-specific symbol_ref flags. */ -#define SYMBOL_FLAG_ALIGN1 (SYMBOL_FLAG_MACH_DEP << 0) -#define SYMBOL_REF_ALIGN1_P(X) \ - ((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_ALIGN1)) -#define SYMBOL_FLAG_NOT_NATURALLY_ALIGNED (SYMBOL_FLAG_MACH_DEP << 1) -#define SYMBOL_REF_NOT_NATURALLY_ALIGNED_P(X) \ - ((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_NOT_NATURALLY_ALIGNED)) +#define SYMBOL_FLAG_ALIGN_SHIFT SYMBOL_FLAG_MACH_DEP_SHIFT +#define SYMBOL_FLAG_ALIGN_MASK \ + ((SYMBOL_FLAG_MACH_DEP << 0) | (SYMBOL_FLAG_MACH_DEP << 1)) + +#define SYMBOL_FLAG_SET_ALIGN(X, A) \ + (SYMBOL_REF_FLAGS (X) = (SYMBOL_REF_FLAGS (X) & ~SYMBOL_FLAG_ALIGN_MASK) \ + | (A << SYMBOL_FLAG_ALIGN_SHIFT)) + +#define SYMBOL_FLAG_GET_ALIGN(X) \ + ((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_ALIGN_MASK) >> SYMBOL_FLAG_ALIGN_SHIFT) + +/* Helpers to access symbol_ref flags. They are used in + check_symref_alignment() and larl_operand to detect if the + available alignment matches the required one. We do not use + a positive check like _ALIGN2 because in that case we would have + to annotate every symbol_ref. However, we only want to touch + the symbol_refs that can be misaligned and assume that the others + are correctly aligned. Hence, if a symbol_ref does not have + a _NOTALIGN flag it is supposed to be correctly aligned. */ +#define SYMBOL_FLAG_SET_NOTALIGN2(X) SYMBOL_FLAG_SET_ALIGN(X, 1) +#define SYMBOL_FLAG_SET_NOTALIGN4(X) SYMBOL_FLAG_SET_ALIGN(X, 2) +#define SYMBOL_FLAG_SET_NOTALIGN8(X) SYMBOL_FLAG_SET_ALIGN(X, 3) + +#define SYMBOL_FLAG_NOTALIGN2_P(X) (SYMBOL_FLAG_GET_ALIGN(X) == 1) +#define SYMBOL_FLAG_NOTALIGN4_P(X) (SYMBOL_FLAG_GET_ALIGN(X) == 2 \ + || SYMBOL_FLAG_GET_ALIGN(X) == 1) +#define SYMBOL_FLAG_NOTALIGN8_P(X) (SYMBOL_FLAG_GET_ALIGN(X) == 3 \ + || SYMBOL_FLAG_GET_ALIGN(X) == 2 \ + || SYMBOL_FLAG_GET_ALIGN(X) == 1) /* Check whether integer displacement is in range for a short displacement. */ #define SHORT_DISP_IN_RANGE(d) ((d) >= 0 && (d) <= 4095) |