diff mbox

Fix arm ICE in output_move_double (PR target/51915)

Message ID 20120120171614.GA18768@tyan-ft48-01.lab.bos.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Jan. 20, 2012, 5:16 p.m. UTC
Hi!

As detailed in the PR, output_move_double sometimes modifies the
operands array it is called on (when it intends to return a template
string that should be output by the caller).  Unfortunately, since
arm_count_output_move_double_insns has been added, this can lead into
clobbering of recog_data.operands already during computation of insn sizes,
and if no other insn is recognized in between that and the output of that
insn, we might be called with second operand of SImode r1 instead of
a MEM and ICE, because it sees a DImode r0 = SImode r1 move.

Fixed thusly, ok for trunk?

2012-01-20  Jakub Jelinek  <jakub@redhat.com>

	PR target/51915
	* config/arm/arm.c (arm_count_output_move_double_insns): Call
	output_move_double on a copy of operands array.

	* gcc.target/arm/pr51915.c: New test.


	Jakub

Comments

Ramana Radhakrishnan Jan. 20, 2012, 5:46 p.m. UTC | #1
> Fixed thusly, ok for trunk?

OK.

Thanks,
Ramana
> 
> 2012-01-20  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR target/51915
> 	* config/arm/arm.c (arm_count_output_move_double_insns): Call
> 	output_move_double on a copy of operands array.
> 
> 	* gcc.target/arm/pr51915.c: New test.
> 
> --- gcc/config/arm/arm.c.jj	2012-01-20 12:35:15.000000000 +0100
> +++ gcc/config/arm/arm.c	2012-01-20 13:51:06.781889121 +0100
> @@ -24664,7 +24664,12 @@ int
>  arm_count_output_move_double_insns (rtx *operands)
>  {
>    int count;
> -  output_move_double (operands, false, &count);
> +  rtx ops[2];
> +  /* output_move_double may modify the operands array, so call it
> +     here on a copy of the array.  */
> +  ops[0] = operands[0];
> +  ops[1] = operands[1];
> +  output_move_double (ops, false, &count);
>    return count;
>  }
>  
> --- gcc/testsuite/gcc.target/arm/pr51915.c.jj	2012-01-20 14:04:38.036245754 +0100
> +++ gcc/testsuite/gcc.target/arm/pr51915.c	2012-01-20 14:04:21.000000000 +0100
> @@ -0,0 +1,13 @@
> +/* PR target/51915 */
> +/* { dg-do compile } */
> +/* { dg-options "-march=armv7-a -mfloat-abi=hard -O2" } */
> +
> +struct S { int s1; void *s2; };
> +struct T { struct S t1; unsigned long long t2; };
> +struct S *foo (unsigned long long);
> +
> +struct S *
> +bar (struct S *x)
> +{
> +  return foo (((struct T *) x)->t2);
> +}
> 
> 	Jakub
>
diff mbox

Patch

--- gcc/config/arm/arm.c.jj	2012-01-20 12:35:15.000000000 +0100
+++ gcc/config/arm/arm.c	2012-01-20 13:51:06.781889121 +0100
@@ -24664,7 +24664,12 @@  int
 arm_count_output_move_double_insns (rtx *operands)
 {
   int count;
-  output_move_double (operands, false, &count);
+  rtx ops[2];
+  /* output_move_double may modify the operands array, so call it
+     here on a copy of the array.  */
+  ops[0] = operands[0];
+  ops[1] = operands[1];
+  output_move_double (ops, false, &count);
   return count;
 }
 
--- gcc/testsuite/gcc.target/arm/pr51915.c.jj	2012-01-20 14:04:38.036245754 +0100
+++ gcc/testsuite/gcc.target/arm/pr51915.c	2012-01-20 14:04:21.000000000 +0100
@@ -0,0 +1,13 @@ 
+/* PR target/51915 */
+/* { dg-do compile } */
+/* { dg-options "-march=armv7-a -mfloat-abi=hard -O2" } */
+
+struct S { int s1; void *s2; };
+struct T { struct S t1; unsigned long long t2; };
+struct S *foo (unsigned long long);
+
+struct S *
+bar (struct S *x)
+{
+  return foo (((struct T *) x)->t2);
+}