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 simplify_comparison in the combiner (PR rtl-optimization/61673)


Hi!

The following testcase is miscompiled on s390-linux (31-bit).
r202393 changed:
@@ -11946,11 +11949,11 @@                                                                                                                          
          if (op1 == const0_rtx && (code == LT || code == GE)                                                                                      
              && HWI_COMPUTABLE_MODE_P (mode))                                                                                                     
            {                                                                                                                                      
+             unsigned HOST_WIDE_INT sign                                                                                                          
+               = (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1);                                                                     
              op0 = simplify_gen_binary (AND, tmode,                                                                                               
                                         gen_lowpart (tmode, op0),                                                                                 
-                                        GEN_INT ((unsigned HOST_WIDE_INT) 1                                                                       
-                                                 << (GET_MODE_BITSIZE (mode)                                                                      
-                                                     - 1)));                                                                                      
+                                        gen_int_mode (sign, mode));                                                                               
              code = (code == LT) ? NE : EQ;                                                                                                       
              break;                                                                                                                               
            }                                                                                                                                      
This code creates AND of a paradoxical subreg where the bits above
mode are undefined, so of course the mask has to check just the single
sign bit rather than that bit + all bits above it.
In this particular testcase, mode is QImode and tmode is SImode,
previously and with my patch we were masking with 128, current 4.9 branch
and trunk masks with -128.

Bootstrapped/regtested on x86_64-linux, i686-linux and s390{,x}-linux.  Ok
for trunk/4.9?

2014-07-03  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/61673
	* combine.c (simplify_comparison): Test just mode's sign bit
	in tmode rather than the sign bit and any bits above it.

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

--- gcc/combine.c.jj	2014-03-28 20:49:52.892077022 +0100
+++ gcc/combine.c	2014-07-02 16:56:02.260456040 +0200
@@ -11987,7 +11987,7 @@ simplify_comparison (enum rtx_code code,
 		= (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1);
 	      op0 = simplify_gen_binary (AND, tmode,
 					 gen_lowpart (tmode, op0),
-					 gen_int_mode (sign, mode));
+					 gen_int_mode (sign, tmode));
 	      code = (code == LT) ? NE : EQ;
 	      break;
 	    }
--- gcc/testsuite/gcc.c-torture/execute/pr61673.c.jj	2014-07-02 17:17:01.398908630 +0200
+++ gcc/testsuite/gcc.c-torture/execute/pr61673.c	2014-07-02 17:12:36.000000000 +0200
@@ -0,0 +1,50 @@
+/* PR rtl-optimization/61673 */
+
+char e;
+
+__attribute__((noinline, noclone)) void
+bar (char x)
+{
+  if (x != 0x54 && x != (char) 0x87)
+    __builtin_abort ();
+}
+
+__attribute__((noinline, noclone)) void
+foo (const char *x)
+{
+  char d = x[0];
+  int c = d;
+  if ((c >= 0 && c <= 0x7f) == 0)
+    e = d;
+  bar (d);
+}
+
+__attribute__((noinline, noclone)) void
+baz (const char *x)
+{
+  char d = x[0];
+  int c = d;
+  if ((c >= 0 && c <= 0x7f) == 0)
+    e = d;
+}
+
+int
+main ()
+{
+  const char c[] = { 0x54, 0x87 };
+  e = 0x21;
+  foo (c);
+  if (e != 0x21)
+    __builtin_abort ();
+  foo (c + 1);
+  if (e != (char) 0x87)
+    __builtin_abort ();
+  e = 0x21;
+  baz (c);
+  if (e != 0x21)
+    __builtin_abort ();
+  baz (c + 1);
+  if (e != (char) 0x87)
+    __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]