diff mbox

[PR,60556] Fix ICE on platforms with signed pointer extension.

Message ID 20140411090755.GQ1817@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek April 11, 2014, 9:07 a.m. UTC
On Thu, Mar 20, 2014 at 09:48:58AM -0700, Steve Ellcey  wrote:
> 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.

I think the right fix is instead to use emit_store_flag_force, that will
force into register only when necessary, and will do so even in the numerous
other cases when emit_store_flag may return NULL (LABEL_REF, other
constants, different branch costs, etc.).

Will bootstrap/regtest this on x86_64-linux and i686-linux, Steve, can you
please test on mips?  Ok for trunk if testing passes?

2014-04-11  Steve Ellcey  <sellcey@mips.com>
	    Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/60556
	* expr.c (convert_move): Use emit_store_flag_force instead of
	emit_store_flag.  Pass lowpart_mode instead of VOIDmode as 5th
	argument to it.

	* gcc.c-torture/compile/pr60556.c: New test.


	Jakub

Comments

Richard Biener April 11, 2014, 9:43 a.m. UTC | #1
On Fri, 11 Apr 2014, Jakub Jelinek wrote:

> On Thu, Mar 20, 2014 at 09:48:58AM -0700, Steve Ellcey  wrote:
> > 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.
> 
> I think the right fix is instead to use emit_store_flag_force, that will
> force into register only when necessary, and will do so even in the numerous
> other cases when emit_store_flag may return NULL (LABEL_REF, other
> constants, different branch costs, etc.).
> 
> Will bootstrap/regtest this on x86_64-linux and i686-linux, Steve, can you
> please test on mips?  Ok for trunk if testing passes?

Ok.

Thanks,
Richard.

> 2014-04-11  Steve Ellcey  <sellcey@mips.com>
> 	    Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR middle-end/60556
> 	* expr.c (convert_move): Use emit_store_flag_force instead of
> 	emit_store_flag.  Pass lowpart_mode instead of VOIDmode as 5th
> 	argument to it.
> 
> 	* gcc.c-torture/compile/pr60556.c: New test.
> 
> --- gcc/expr.c.jj	2014-03-28 23:06:44.000000000 +0100
> +++ gcc/expr.c	2014-04-11 10:59:24.664014557 +0200
> @@ -551,9 +551,9 @@ convert_move (rtx to, rtx from, int unsi
>        if (unsignedp)
>  	fill_value = const0_rtx;
>        else
> -	fill_value = emit_store_flag (gen_reg_rtx (word_mode),
> -				      LT, lowfrom, const0_rtx,
> -				      VOIDmode, 0, -1);
> +	fill_value = emit_store_flag_force (gen_reg_rtx (word_mode),
> +					    LT, lowfrom, const0_rtx,
> +					    lowpart_mode, 0, -1);
>  
>        /* Fill the remaining words.  */
>        for (i = GET_MODE_SIZE (lowpart_mode) / UNITS_PER_WORD; i < nwords; i++)
> --- gcc/testsuite/gcc.c-torture/compile/pr60556.c.jj	2014-04-11 11:01:53.535218278 +0200
> +++ gcc/testsuite/gcc.c-torture/compile/pr60556.c	2014-04-11 11:01:53.535218278 +0200
> @@ -0,0 +1,8 @@
> +/* PR middle-end/60556 */
> +
> +int g (int);
> +
> +unsigned long long f (void)
> +{
> + return (unsigned long long)(long)&g;
> +}
diff mbox

Patch

--- gcc/expr.c.jj	2014-03-28 23:06:44.000000000 +0100
+++ gcc/expr.c	2014-04-11 10:59:24.664014557 +0200
@@ -551,9 +551,9 @@  convert_move (rtx to, rtx from, int unsi
       if (unsignedp)
 	fill_value = const0_rtx;
       else
-	fill_value = emit_store_flag (gen_reg_rtx (word_mode),
-				      LT, lowfrom, const0_rtx,
-				      VOIDmode, 0, -1);
+	fill_value = emit_store_flag_force (gen_reg_rtx (word_mode),
+					    LT, lowfrom, const0_rtx,
+					    lowpart_mode, 0, -1);
 
       /* Fill the remaining words.  */
       for (i = GET_MODE_SIZE (lowpart_mode) / UNITS_PER_WORD; i < nwords; i++)
--- gcc/testsuite/gcc.c-torture/compile/pr60556.c.jj	2014-04-11 11:01:53.535218278 +0200
+++ gcc/testsuite/gcc.c-torture/compile/pr60556.c	2014-04-11 11:01:53.535218278 +0200
@@ -0,0 +1,8 @@ 
+/* PR middle-end/60556 */
+
+int g (int);
+
+unsigned long long f (void)
+{
+ return (unsigned long long)(long)&g;
+}