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 up make_compound_operation (PR rtl-optimization/57130)


Hi!

As described in the PR, in some cases it is unsafe for
make_compound_operation, if called with in_code == COMPARE,
to pass through that value to make_compound_operation on
the SUBREG_REG of a SUBREG.

My understanding is that in_code == COMPARE (as opposed to
in_code == SET) is mostly harmless, just tells make_extraction
to no longer special case zero extraction at position 0, but there is one
exception - AND with constant power of two CONST_INT.
If we have
make_compound_operation ( (subreg:SI (and:DI (reg:DI) (const_int 0x800000000)) 0), COMPARE)
then
make_compound_operation ( (and:DI (reg:DI) (const_int 0x800000000)), COMPARE)
returns extraction of the 35th bit, and subreg of that is again either zero
or one, but the original subreg is always 0.

Fixed by passing through SET instead of in_code to the recursive invocation,
if
1) the subreg isn't lowpart
2) nested SUBREGs (should be usually simplified, but just in case it hasn't been yet)
3) if subreg's operand is AND with power of two CONST_INT above the bitsize
   of the outer mode

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

2013-05-02  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/57130
	* combine.c (make_compound_operation): For SUBREG, pass
	SET instead of COMPARE as in_code to the recursive call
	if needed.

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

--- gcc/combine.c.jj	2013-04-11 09:09:39.000000000 +0200
+++ gcc/combine.c	2013-05-02 12:46:07.540196281 +0200
@@ -7697,8 +7697,24 @@ make_compound_operation (rtx x, enum rtx
 	 what it originally did, do this SUBREG as a force_to_mode.  */
       {
 	rtx inner = SUBREG_REG (x), simplified;
-	
-	tem = make_compound_operation (inner, in_code);
+	enum rtx_code subreg_code = in_code;
+
+	/* If in_code is COMPARE, it isn't always safe to pass it through
+	   to the recursive make_compound_operation call.  */
+	if (subreg_code == COMPARE
+	    && (!subreg_lowpart_p (x)
+		|| GET_CODE (inner) == SUBREG
+		/* (subreg:SI (and:DI (reg:DI) (const_int 0x800000000)) 0)
+		   is (const_int 0), rather than
+		   (subreg:SI (lshiftrt:DI (reg:DI) (const_int 35)) 0).  */
+		|| (GET_CODE (inner) == AND
+		    && CONST_INT_P (XEXP (inner, 1))
+		    && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (inner))
+		    && exact_log2 (UINTVAL (XEXP (inner, 1)))
+		       >= GET_MODE_BITSIZE (mode))))
+	  subreg_code = SET;
+
+	tem = make_compound_operation (inner, subreg_code);
 
 	simplified
 	  = simplify_subreg (mode, tem, GET_MODE (inner), SUBREG_BYTE (x));
--- gcc/testsuite/gcc.c-torture/execute/pr57130.c.jj	2013-05-02 10:52:00.389263977 +0200
+++ gcc/testsuite/gcc.c-torture/execute/pr57130.c	2013-05-02 10:51:45.000000000 +0200
@@ -0,0 +1,21 @@
+/* PR rtl-optimization/57130 */
+
+struct S { int a, b, c, d; } s[2] = { { 6, 8, -8, -5 }, { 0, 2, -1, 2 } };
+
+__attribute__((noinline, noclone)) void
+foo (struct S r)
+{
+  static int cnt;
+  if (__builtin_memcmp (&r, &s[cnt++], sizeof r) != 0)
+    __builtin_abort ();
+}
+
+int
+main ()
+{
+  struct S r = { 6, 8, -8, -5 };
+  foo (r);
+  r = (struct S) { 0, 2, -1, 2 };
+  foo (r);
+  return 0;
+}

	Jakub


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