[PATCH 2/6] rs6000: Do not allow lo_sum accesses >= 4 bytes if unaligned
Segher Boessenkool
segher@kernel.crashing.org
Sat Jan 17 08:49:00 GMT 2015
This fixes 29 FAILs.
The ld, lwa etc. insns do not encode the low two bits of the offset in
the opcode; those have to be zero. For -m64 this seemed to never matter,
datums are always aligned; but for -m32 -mpowerpc64 you can get symbols
that are not sufficiently aligned. So check for that.
[ Hrm, I think this triggers for lwz as well? I'll investigate. ]
2015-01-16 Segher Boessenkool <segher@kernel.crashing.org>
gcc/
* config/rs6000/rs6000.c (lo_sum_symbol_misaligned_p): New function.
(legitimate_lo_sum_address_p): Use it for TARGET_POWERPC64.
---
gcc/config/rs6000/rs6000.c | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 551181b..53bee13 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -6735,6 +6735,39 @@ macho_lo_sum_memory_operand (rtx x, machine_mode mode)
return CONSTANT_P (x);
}
+/* Return true if X (which is the second operand of a LO_SUM) is a symbol
+ that is not sufficiently aligned for a DS-form instruction. */
+static bool
+lo_sum_symbol_misaligned_p (rtx x)
+{
+ if (GET_CODE (x) == CONST)
+ x = XEXP (x, 0);
+
+ if (GET_CODE (x) == PLUS)
+ x = XEXP (x, 0);
+
+ if (GET_CODE (x) != SYMBOL_REF)
+ return false;
+
+ tree decl = SYMBOL_REF_DECL (x);
+ if (decl)
+ return DECL_ALIGN_UNIT (decl) < 4;
+
+ if (SYMBOL_REF_HAS_BLOCK_INFO_P (x)
+ && SYMBOL_REF_ANCHOR_P (x))
+ {
+ struct object_block *block = SYMBOL_REF_BLOCK (x);
+ if (block)
+ return block->alignment < 32;
+ }
+
+ if (CONSTANT_POOL_ADDRESS_P (x))
+ return GET_MODE_ALIGNMENT (get_pool_mode (x)) < 32;
+
+ /* Assume it's okay otherwise. */
+ return false;
+}
+
static bool
legitimate_lo_sum_address_p (machine_mode mode, rtx x, int strict)
{
@@ -6774,6 +6807,10 @@ legitimate_lo_sum_address_p (machine_mode mode, rtx x, int strict)
TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
&& (mode == DFmode || mode == DDmode)))
return false;
+ if (TARGET_POWERPC64
+ && GET_MODE_SIZE (mode) >= 4
+ && lo_sum_symbol_misaligned_p (x))
+ return false;
return CONSTANT_P (x) || large_toc_ok;
}
--
1.8.1.4
More information about the Gcc-patches
mailing list