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 testqi_ext_3* on x86_64 (PR tree-optimization/25554)


Hi!

testqi_ext_3* doesn't check that len is positive and pos non-negative,
but the pos/len checks as well as the splitter relies on it.
The bad values can get either by compiling undefined behavior code
(shifting by negative count), or e.g. with -ftracer.
On the other side, testqi_ext_3_rex64 used
INTVAL (operands[1]) + INTVAL (operands[2]) < HOST_BITS_PER_WIDE_INT
&& ... (INTVAL (operands[1]) + INTVAL (operands[2]) == 64
but I doubt HOST_BITS_PER_WIDE_INT is ever 128, so the sign extended
testqi would never trigger, eventhough it can be handled easily.

Ok for 4.0/4.1/trunk if testing succeeds?

2005-12-28  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/25554
	* config/i386/i386.md (testqi_ext_3): Ensure len is positive
	and pos non-negative and pos + len <= 32.
	(testqi_ext_3_rex64): Ensure len is positive and pos non-negative,
	drop pos + len < HOST_BITS_PER_WIDE_INT test.
	(testqi_ext_3* splitter): Handle pos + len == HOST_BITS_PER_WIDE_INT.

	* gcc.c-torture/compile/20051228-1.c: New test.

--- gcc/config/i386/i386.md.jj	2005-12-13 09:07:50.000000000 +0100
+++ gcc/config/i386/i386.md	2005-12-28 15:32:41.000000000 +0100
@@ -7865,6 +7865,9 @@
 		   (match_operand:SI 2 "const_int_operand" ""))
 		 (const_int 0)))]
   "ix86_match_ccmode (insn, CCNOmode)
+   && INTVAL (operands[1]) > 0
+   && INTVAL (operands[2]) >= 0
+   && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32
    && (GET_MODE (operands[0]) == SImode
        || (TARGET_64BIT && GET_MODE (operands[0]) == DImode)
        || GET_MODE (operands[0]) == HImode
@@ -7880,8 +7883,8 @@
 		 (const_int 0)))]
   "TARGET_64BIT
    && ix86_match_ccmode (insn, CCNOmode)
-   /* The code below cannot deal with constants outside HOST_WIDE_INT.  */
-   && INTVAL (operands[1]) + INTVAL (operands[2]) < HOST_BITS_PER_WIDE_INT
+   && INTVAL (operands[1]) > 0
+   && INTVAL (operands[2]) >= 0
    /* Ensure that resulting mask is zero or sign extended operand.  */
    && (INTVAL (operands[1]) + INTVAL (operands[2]) <= 32
        || (INTVAL (operands[1]) + INTVAL (operands[2]) == 64
@@ -7936,8 +7939,11 @@
       val = gen_lowpart (QImode, val);
     }
 
-  mask  = ((HOST_WIDE_INT)1 << (pos + len)) - 1;
-  mask &= ~(((HOST_WIDE_INT)1 << pos) - 1);
+  if (len == HOST_BITS_PER_WIDE_INT)
+    mask = -1;
+  else
+    mask = ((HOST_WIDE_INT)1 << len) - 1;
+  mask <<= pos;
 
   operands[2] = gen_rtx_AND (mode, val, gen_int_mode (mask, mode));
 })
--- gcc/testsuite/gcc.c-torture/compile/20051228-1.c.jj	2005-12-28 15:53:45.000000000 +0100
+++ gcc/testsuite/gcc.c-torture/compile/20051228-1.c	2005-12-28 15:53:29.000000000 +0100
@@ -0,0 +1,10 @@
+/* PR tree-optimization/25554 */
+/* Bitwise shift with negative shift count has undefined behavior,
+   but we shouldn't ICE on it.  */
+
+void
+foo (long x)
+{
+  if (((x >> -2) & 1) != 0)
+    bar ();
+}

	Jakub


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