As reported in PR78554, attempting to store an __int20 address in memory
causes an ICE due to an invalid insn. This only occurs at optimisation
levels higher than -O0 because these optimisation levels pass
-ftree-ter, which causes the compiler to try and do the store in
one instruction.
The issue in the insn is that a SUBREG references a SYMBOL_REF.

I guess the compiler gets into this situation because it assumes that
it can execute a move instruction where both src and dst are in memory,
but this isn't possible with __int20.

The attached patch prevents a instance of SUBREG being created where the
subword is a SYMBOL_REF.

If the patch is acceptable, I would appreciate if someone could commit
it for me, as I do not have write access.

Thanks,
Jozef
From 72a419c1f470254f06c59c7824ae27818a18b555 Mon Sep 17 00:00:00 2001
From: Jozef Lawrynowicz <joze...@somniumtech.com>
Date: Thu, 24 Aug 2017 12:08:36 +0000
Subject: [PATCH] MSP430: Prevent SUBREG from referencing a SYMBOL_REF

2017-08-XX      Jozef Lawrynowicz       <joze...@somniumtech.com>

        PR target/78554
        * gcc/emit-rtl.c (operand_subword): Dont pass SYMBOL_REF operand to
        simplify_gen_subreg.
        
gcc/testsuite
2017-08-XX      Jozef Lawrynowicz       <joze...@somniumtech.com>

        PR target/78554
        * gcc.target/msp430/pr78554.c: New test.
---
 gcc/emit-rtl.c                            |  5 +++++
 gcc/testsuite/gcc.target/msp430/pr78554.c | 20 ++++++++++++++++++++
 2 files changed, 25 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/msp430/pr78554.c

diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index c1438d6..c655605 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -1596,6 +1596,11 @@ operand_subword (rtx op, unsigned int offset, int 
validate_address, machine_mode
       && (offset + 1) * UNITS_PER_WORD > GET_MODE_SIZE (mode))
     return const0_rtx;
 
+  /* TER can cause SYMBOL_REFs to arrive here.  Don't pass them to
+     simplify_gen_subreg.  */
+  if (SYMBOL_REF_P (op))
+    return 0;
+
   /* Form a new MEM at the requested address.  */
   if (MEM_P (op))
     {
diff --git a/gcc/testsuite/gcc.target/msp430/pr78554.c 
b/gcc/testsuite/gcc.target/msp430/pr78554.c
new file mode 100644
index 0000000..aca98cc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/msp430/pr78554.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { "*-*-*" } { "-mcpu=msp430" "-msmall" } { "" } } */
+/* { dg-options "-O1 -mlarge -mcpu=msp430x" } */
+
+unsigned char test_val = 0;
+
+typedef __int20 unsigned reg_t;
+
+struct holds_reg
+{
+  reg_t r0;
+};
+
+struct holds_reg ex = { 0 };
+
+int main (void)
+{
+  ex.r0 = (reg_t)(&test_val);
+  return 0;
+}
-- 
1.8.3.1

Reply via email to