This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix force_to_mode not to modify in place the passed rtl (PR rtl-optimization/58726)


Hi!

As described in the PR, the problem here is that during combine
i2 pattern is substituted into more than one place in i3 pattern,
unique_copy is 0 (but, even if it would be non-zero, it could happen
if the comparison was processed first before the normal set inside of the
parallel) and thus the same RTL is (temporarily) shared between two
locations.  force_to_mode is first called with mask 0xdc36 (that is
actually find for both occurrences in the andhi_2 pattern) and later on
inside of the comparison again with mask 0x8000, and as it modifies
the IF_THEN_ELSE in place, it modifies also the other location (it is fine
if the comparison uses 0x8000 mask, but not in the other spot).
As in the end we fold it to a constant, we don't undo it and use incorrect
constant.

Fixed by making sure force_to_mode doesn't modify x in place.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/4.8?

2013-12-03  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/58726
	* combine.c (force_to_mode): Fix comment typo.  Don't destructively
	modify x for ROTATE, ROTATERT and IF_THEN_ELSE.

	* gcc.c-torture/execute/pr58726.c: New test.

--- gcc/combine.c.jj	2013-12-02 14:33:34.000000000 +0100
+++ gcc/combine.c	2013-12-03 20:37:25.140274452 +0100
@@ -8029,7 +8029,7 @@ force_to_mode (rtx x, enum machine_mode
   if (code == CALL || code == ASM_OPERANDS || code == CLOBBER)
     return x;
 
-  /* We want to perform the operation is its present mode unless we know
+  /* We want to perform the operation in its present mode unless we know
      that the operation is valid in MODE, in which case we do the operation
      in MODE.  */
   op_mode = ((GET_MODE_CLASS (mode) == GET_MODE_CLASS (GET_MODE (x))
@@ -8460,9 +8460,10 @@ force_to_mode (rtx x, enum machine_mode
 					    gen_int_mode (mask, GET_MODE (x)),
 					    XEXP (x, 1));
 	  if (temp && CONST_INT_P (temp))
-	    SUBST (XEXP (x, 0),
-		   force_to_mode (XEXP (x, 0), GET_MODE (x),
-				  INTVAL (temp), next_select));
+	    x = simplify_gen_binary (code, GET_MODE (x),
+				     force_to_mode (XEXP (x, 0), GET_MODE (x),
+						    INTVAL (temp), next_select),
+				     XEXP (x, 1));
 	}
       break;
 
@@ -8530,14 +8531,16 @@ force_to_mode (rtx x, enum machine_mode
       /* We have no way of knowing if the IF_THEN_ELSE can itself be
 	 written in a narrower mode.  We play it safe and do not do so.  */
 
-      SUBST (XEXP (x, 1),
-	     gen_lowpart_or_truncate (GET_MODE (x),
-				      force_to_mode (XEXP (x, 1), mode,
-						     mask, next_select)));
-      SUBST (XEXP (x, 2),
-	     gen_lowpart_or_truncate (GET_MODE (x),
-				      force_to_mode (XEXP (x, 2), mode,
-						     mask, next_select)));
+      op0 = gen_lowpart_or_truncate (GET_MODE (x),
+				     force_to_mode (XEXP (x, 1), mode,
+						    mask, next_select));
+      op1 = gen_lowpart_or_truncate (GET_MODE (x),
+				     force_to_mode (XEXP (x, 2), mode,
+						    mask, next_select));
+      if (op0 != XEXP (x, 1) || op1 != XEXP (x, 2))
+	x = simplify_gen_ternary (IF_THEN_ELSE, GET_MODE (x),
+				  GET_MODE (XEXP (x, 0)), XEXP (x, 0),
+				  op0, op1);
       break;
 
     default:
--- gcc/testsuite/gcc.c-torture/execute/pr58726.c.jj	2013-12-03 20:47:41.024094847 +0100
+++ gcc/testsuite/gcc.c-torture/execute/pr58726.c	2013-12-03 20:47:24.000000000 +0100
@@ -0,0 +1,26 @@
+/* PR rtl-optimization/58726 */
+
+int a, c;
+union { int f1; int f2 : 1; } b;
+
+short
+foo (short p)
+{
+  return p < 0 ? p : a;
+}
+
+int
+main ()
+{
+  if (sizeof (short) * __CHAR_BIT__ != 16
+      || sizeof (int) * __CHAR_BIT__ != 32)
+    return 0;
+  b.f1 = 56374;
+  unsigned short d;
+  int e = b.f2;
+  d = e == 0 ? b.f1 : 0;
+  c = foo (d);
+  if (c != (short) 56374)
+    __builtin_abort ();
+  return 0;
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]