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; +}