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