This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix testqi_ext_3* on x86_64 (PR tree-optimization/25554)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 28 Dec 2005 10:07:11 -0500
- Subject: [PATCH] Fix testqi_ext_3* on x86_64 (PR tree-optimization/25554)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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