This patch fixes pr60556, a GCC ICE.  The problem is in convert_move where,
if we are trying to put a 32 bit address into a 64 bit destination we
can wind up calling emit_move_insn with NULL_RTX as a source.

The problem comes when creating fill_value.  If unsignedp is false
then we call emit_store_flag to set fill_value.  If lowfrom is a symbol
reference then emit_store_flag returns NULL_RTX (because symbol references
are constant) and we wind up calling emit_move_insn with NULL_RTX as a
source and getting an ICE.

My fix is to check for a symbol reference up where we are already 
checking for memory references and force the symbol into a register
before calling emit_store_flag.  This will prevent emit_store_flag
from returning NULL_RTX.  In theory we could force the symbol
reference into a register only if unsignedp is false, but I think
it is cleaner to always put the symbol reference into a register.

Tested on mips-mti-linux-gnu with no regressions.

OK for checkin?

Steve Ellcey
sell...@mips.com


2014-03-20  Steve Ellcey  <sell...@mips.com>

        PR middle-end/60556
        * expr.c (convert_move): Force symbol references into register.


diff --git a/gcc/expr.c b/gcc/expr.c
index be62c53..d065588 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -533,7 +533,8 @@ convert_move (rtx to, rtx from, int unsignedp)
          conversion sequence might require several references to it and we
          must ensure we're getting the same value every time.  */
 
-      if (MEM_P (from) || reg_overlap_mentioned_p (to, from))
+      if (MEM_P (from) || GET_CODE (from) == SYMBOL_REF
+         || reg_overlap_mentioned_p (to, from))
        from = force_reg (from_mode, from);
 
       /* Get a copy of FROM widened to a word, if necessary.  */



2014-03-20  Steve Ellcey  <sell...@mips.com>

        PR middle-end/60556
        gcc.dg/pr60556.c: New.


diff --git a/gcc/testsuite/gcc.dg/pr60556.c b/gcc/testsuite/gcc.dg/pr60556.c
new file mode 100644
index 0000000..3b5bbe5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr60556.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+int g (int);
+unsigned long long f(void) {
+ return (unsigned long long)(long)&g;
+}

Reply via email to