[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